* [PATCH 01/14] mtd: nand: nand-mxs: Move register definitions to separate file
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-02 8:08 ` Marco Felsch
2022-11-01 15:30 ` [PATCH 02/14] ARM: i.MX: xload nand: Use common register defines Sascha Hauer
` (12 subsequent siblings)
13 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
The GPMI registers are needed in the MTD GPMI driver and also in the
xload-gpmi driver. So far both use their own set of register defines.
Move the MTD GPMI register defines to include/ so that we can use them
in the xload driver as well.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mtd/nand/nand_mxs.c | 186 ++++++------------------------------
include/soc/imx/gpmi-nand.h | 114 ++++++++++++++++++++++
2 files changed, 145 insertions(+), 155 deletions(-)
create mode 100644 include/soc/imx/gpmi-nand.h
diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index 5faa17a4bd..d711708ff2 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/bitfield.h>
#include <of_mtd.h>
#include <common.h>
#include <dma.h>
@@ -32,139 +33,10 @@
#include <dma/apbh-dma.h>
#include <stmp-device.h>
#include <mach/generic.h>
+#include <soc/imx/gpmi-nand.h>
#include "internals.h"
-#define MX28_BLOCK_SFTRST (1 << 31)
-#define MX28_BLOCK_CLKGATE (1 << 30)
-
-#define GPMI_CTRL0 0x00000000
-#define GPMI_CTRL0_RUN (1 << 29)
-#define GPMI_CTRL0_DEV_IRQ_EN (1 << 28)
-/* Disable for now since we don't need it and it is different on MX23.
-#define GPMI_CTRL0_LOCK_CS (1 << 27)
-*/
-#define GPMI_CTRL0_UDMA (1 << 26)
-#define GPMI_CTRL0_COMMAND_MODE_MASK (0x3 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_OFFSET 24
-#define GPMI_CTRL0_COMMAND_MODE_WRITE (0x0 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_READ (0x1 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE (0x2 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY (0x3 << 24)
-#define GPMI_CTRL0_WORD_LENGTH (1 << 23)
-/* Careful: Is 0x3 on MX23
-#define GPMI_CTRL0_CS_MASK (0x7 << 20)
-*/
-#define GPMI_CTRL0_CS_OFFSET 20
-#define GPMI_CTRL0_ADDRESS_MASK (0x7 << 17)
-#define GPMI_CTRL0_ADDRESS_OFFSET 17
-#define GPMI_CTRL0_ADDRESS_NAND_DATA (0x0 << 17)
-#define GPMI_CTRL0_ADDRESS_NAND_CLE (0x1 << 17)
-#define GPMI_CTRL0_ADDRESS_NAND_ALE (0x2 << 17)
-#define GPMI_CTRL0_ADDRESS_INCREMENT (1 << 16)
-#define GPMI_CTRL0_XFER_COUNT_MASK 0xffff
-#define GPMI_CTRL0_XFER_COUNT_OFFSET 0
-
-#define GPMI_CTRL1 0x00000060
-#define GPMI_CTRL1_SET 0x00000064
-#define GPMI_CTRL1_CLR 0x00000068
-#define GPMI_CTRL1_DECOUPLE_CS (1 << 24)
-#define GPMI_CTRL1_WRN_DLY(d) (((d) & 0x3) << 22)
-#define GPMI_CTRL1_TIMEOUT_IRQ_EN (1 << 20)
-#define GPMI_CTRL1_GANGED_RDYBUSY (1 << 19)
-#define GPMI_CTRL1_BCH_MODE (1 << 18)
-#define GPMI_CTRL1_DLL_ENABLE (1 << 17)
-#define GPMI_CTRL1_HALF_PERIOD (1 << 16)
-#define GPMI_CTRL1_RDN_DELAY(d) (((d) & 0xf) << 12)
-#define GPMI_CTRL1_DMA2ECC_MODE (1 << 11)
-#define GPMI_CTRL1_DEV_IRQ (1 << 10)
-#define GPMI_CTRL1_TIMEOUT_IRQ (1 << 9)
-#define GPMI_CTRL1_BURST_EN (1 << 8)
-#define GPMI_CTRL1_ABORT_WAIT_REQUEST (1 << 7)
-#define GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK (0x7 << 4)
-#define GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET 4
-#define GPMI_CTRL1_DEV_RESET (1 << 3)
-#define GPMI_CTRL1_ATA_IRQRDY_POLARITY (1 << 2)
-#define GPMI_CTRL1_CAMERA_MODE (1 << 1)
-#define GPMI_CTRL1_GPMI_MODE (1 << 0)
-
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS 0x0
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_6_TO_10NS 0x1
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_7_TO_12NS 0x2
-#define BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY 0x3
-
-#define GPMI_TIMING0 0x00000070
-
-#define GPMI_TIMING0_ADDRESS_SETUP(d) (((d) & 0xff) << 16)
-#define GPMI_TIMING0_DATA_HOLD(d) (((d) & 0xff) << 8)
-#define GPMI_TIMING0_DATA_SETUP(d) (((d) & 0xff) << 0)
-
-#define GPMI_TIMING1 0x00000080
-#define GPMI_TIMING1_BUSY_TIMEOUT(d) (((d) & 0xffff) << 16)
-
-#define GPMI_ECCCTRL_HANDLE_MASK (0xffff << 16)
-#define GPMI_ECCCTRL_HANDLE_OFFSET 16
-#define GPMI_ECCCTRL_ECC_CMD_MASK (0x3 << 13)
-#define GPMI_ECCCTRL_ECC_CMD_OFFSET 13
-#define GPMI_ECCCTRL_ECC_CMD_DECODE (0x0 << 13)
-#define GPMI_ECCCTRL_ECC_CMD_ENCODE (0x1 << 13)
-#define GPMI_ECCCTRL_RANDOMIZER_ENABLE (1 << 11)
-#define GPMI_ECCCTRL_RANDOMIZER_TYPE0 0
-#define GPMI_ECCCTRL_RANDOMIZER_TYPE1 (1 << 9)
-#define GPMI_ECCCTRL_RANDOMIZER_TYPE2 (2 << 9)
-#define GPMI_ECCCTRL_ENABLE_ECC (1 << 12)
-#define GPMI_ECCCTRL_BUFFER_MASK_MASK 0x1ff
-#define GPMI_ECCCTRL_BUFFER_MASK_OFFSET 0
-#define GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY 0x100
-#define GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE 0x1ff
-
-#define GPMI_STAT 0x000000b0
-#define GPMI_STAT_READY_BUSY_OFFSET 24
-
-#define GPMI_DEBUG 0x000000c0
-#define GPMI_DEBUG_READY0_OFFSET 28
-
-#define GPMI_VERSION 0x000000d0
-#define GPMI_VERSION_MINOR_OFFSET 16
-#define GPMI_VERSION_TYPE_MX23 0x0300
-
-#define BCH_CTRL 0x00000000
-#define BCH_CTRL_COMPLETE_IRQ (1 << 0)
-#define BCH_CTRL_COMPLETE_IRQ_EN (1 << 8)
-
-#define BCH_LAYOUTSELECT 0x00000070
-
-#define BCH_FLASH0LAYOUT0 0x00000080
-#define BCH_FLASHLAYOUT0_NBLOCKS_MASK (0xff << 24)
-#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24
-#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16)
-#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16
-#define BCH_FLASHLAYOUT0_ECC0_MASK (0xf << 12)
-#define BCH_FLASHLAYOUT0_ECC0_OFFSET 12
-#define IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET 11
-#define BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET 0
-#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_MASK BIT(10)
-#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET 10
-
-#define BCH_FLASH0LAYOUT1 0x00000090
-#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16)
-#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16
-#define BCH_FLASHLAYOUT1_ECCN_MASK (0xf << 12)
-#define BCH_FLASHLAYOUT1_ECCN_OFFSET 12
-#define IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET 11
-#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK BIT(10)
-#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET 10
-#define BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET 0
-
-#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
-
-#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
-#define MXS_NAND_METADATA_SIZE 10
-
-#define MXS_NAND_COMMAND_BUFFER_SIZE 32
-
-#define MXS_NAND_BCH_TIMEOUT 10000
-
enum gpmi_type {
GPMI_MXS,
GPMI_IMX6,
@@ -503,7 +375,7 @@ static void mxs_nand_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctr
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
nand_info->cmd_queue_len;
@@ -634,7 +506,7 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
length;
@@ -659,7 +531,7 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
mxs_dma_desc_append(channel, d);
@@ -713,7 +585,7 @@ static void mxs_nand_write_buf(struct nand_chip *chip, const uint8_t *buf,
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
length;
@@ -749,16 +621,22 @@ static void mxs_nand_config_bch(struct nand_chip *chip, int readlen)
else
chunk_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
- fl0 = (mxs_nand_ecc_chunk_cnt(readlen) - 1)
- << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
- fl0 |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
- fl0 |= (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET;
- fl0 |= chunk_size;
+ fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, mxs_nand_ecc_chunk_cnt(readlen) - 1);
+ fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, MXS_NAND_METADATA_SIZE);
+ if (mxs_nand_is_imx6(nand_info))
+ fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, chip->ecc.strength >> 1);
+ else
+ fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_ECC0, chip->ecc.strength >> 1);
+ fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, chunk_size);
writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
- fl1 = readlen << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
- fl1 |= (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET;
- fl1 |= chunk_size;
+ fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, readlen);
+ if (mxs_nand_is_imx6(nand_info))
+ fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, chip->ecc.strength >> 1);
+ else
+ fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_ECCN, chip->ecc.strength >> 1);
+
+ fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, chunk_size);
writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
}
@@ -781,7 +659,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
mxs_dma_desc_append(channel, d);
@@ -797,7 +675,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
readtotal;
d->cmd.pio_words[1] = 0;
@@ -829,7 +707,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
readtotal;
d->cmd.pio_words[1] = 0;
@@ -1037,7 +915,7 @@ static int mxs_nand_ecc_write_page(struct nand_chip *chip, const uint8_t *buf,
d->cmd.pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
+ FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
d->cmd.pio_words[1] = 0;
d->cmd.pio_words[2] =
@@ -1276,23 +1154,21 @@ static void mxs_nand_mode_fcb_62bit(struct mxs_nand_info *nand_info)
bch_regs = nand_info->bch_base;
/* 8 ecc_chunks */
- fl0 = 7 << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+ fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, 7);
/* 32 bytes for metadata */
- fl0 |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+ fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, 32);
/* using ECC62 level to be performed */
- fl0 |= 0x1F << IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET;
+ fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, 0x1f);
/* 0x20 * 4 bytes of the data0 block */
- fl0 |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
- fl0 |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
+ fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, 0x20);
writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
/* 1024 for data + 838 for OOB */
- fl1 = BCH62_PAGESIZE << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+ fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, BCH62_PAGESIZE);
/* using ECC62 level to be performed */
- fl1 |= 0x1f << IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET;
+ fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, 0x1f);
/* 0x20 * 4 bytes of the data0 block */
- fl1 |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
- fl1 |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
+ fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, 0x20);
writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
}
diff --git a/include/soc/imx/gpmi-nand.h b/include/soc/imx/gpmi-nand.h
new file mode 100644
index 0000000000..f7a2caa1d6
--- /dev/null
+++ b/include/soc/imx/gpmi-nand.h
@@ -0,0 +1,114 @@
+#ifndef __SOC_IMX_GPMI_NAND_H
+#define __SOC_IMX_GPMI_NAND_H
+
+#include <linux/bitfield.h>
+
+#define GPMI_CTRL0 0x00000000
+#define GPMI_CTRL0_SFTRST BIT(31)
+#define GPMI_CTRL0_RUN BIT(29)
+#define GPMI_CTRL0_DEV_IRQ_EN BIT(28)
+#define GPMI_CTRL0_UDMA BIT(26)
+#define GPMI_CTRL0_COMMAND_MODE GENMASK(25, 24)
+#define GPMI_CTRL0_COMMAND_MODE_WRITE (0x0 << 24)
+#define GPMI_CTRL0_COMMAND_MODE_READ (0x1 << 24)
+#define GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE (0x2 << 24)
+#define GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY (0x3 << 24)
+#define GPMI_CTRL0_WORD_LENGTH (1 << 23)
+#define GPMI_CTRL0_CS GENMASK(22, 20)
+#define GPMI_CTRL0_ADDRESS GENMASK(19, 17)
+#define GPMI_CTRL0_ADDRESS_NAND_DATA (0x0 << 17)
+#define GPMI_CTRL0_ADDRESS_NAND_CLE (0x1 << 17)
+#define GPMI_CTRL0_ADDRESS_NAND_ALE (0x2 << 17)
+#define GPMI_CTRL0_ADDRESS_INCREMENT BIT(16)
+#define GPMI_CTRL0_XFER_COUNT GENMASK(15, 0)
+
+#define GPMI_CTRL1 0x00000060
+#define GPMI_CTRL1_SET 0x00000064
+#define GPMI_CTRL1_CLR 0x00000068
+#define GPMI_CTRL1_DECOUPLE_CS BIT(24)
+#define GPMI_CTRL1_WRN_DLY(d) (((d) & 0x3) << 22)
+#define GPMI_CTRL1_TIMEOUT_IRQ_EN BIT(20)
+#define GPMI_CTRL1_GANGED_RDYBUSY BIT(19)
+#define GPMI_CTRL1_BCH_MODE BIT(18)
+#define GPMI_CTRL1_DLL_ENABLE BIT(17)
+#define GPMI_CTRL1_HALF_PERIOD BIT(16)
+#define GPMI_CTRL1_RDN_DELAY(d) (((d) & 0xf) << 12)
+#define GPMI_CTRL1_DMA2ECC_MODE BIT(11)
+#define GPMI_CTRL1_DEV_IRQ BIT(10)
+#define GPMI_CTRL1_TIMEOUT_IRQ BIT(9)
+#define GPMI_CTRL1_BURST_EN BIT(8)
+#define GPMI_CTRL1_ABORT_WAIT_REQUEST BIT(7)
+#define GPMI_CTRL1_ABORT_WAIT_FOR_READY GENMASK(6, 4)
+#define GPMI_CTRL1_DEV_RESET BIT(3)
+#define GPMI_CTRL1_ATA_IRQRDY_POLARITY BIT(2)
+#define GPMI_CTRL1_CAMERA_MODE BIT(1)
+#define GPMI_CTRL1_GPMI_MODE BIT(0)
+
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS 0x0
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_6_TO_10NS 0x1
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_7_TO_12NS 0x2
+#define BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY 0x3
+
+#define GPMI_TIMING0 0x00000070
+
+#define GPMI_TIMING0_ADDRESS_SETUP(d) (((d) & 0xff) << 16)
+#define GPMI_TIMING0_DATA_HOLD(d) (((d) & 0xff) << 8)
+#define GPMI_TIMING0_DATA_SETUP(d) (((d) & 0xff) << 0)
+
+#define GPMI_TIMING1 0x00000080
+#define GPMI_TIMING1_BUSY_TIMEOUT(d) (((d) & 0xffff) << 16)
+
+#define GPMI_ECCCTRL_HANDLE GENMASK(31, 16)
+#define GPMI_ECCCTRL_ECC_CMD GENMASK(14, 13)
+#define GPMI_ECCCTRL_ECC_CMD_DECODE (0x0 << 13)
+#define GPMI_ECCCTRL_ECC_CMD_ENCODE (0x1 << 13)
+#define GPMI_ECCCTRL_RANDOMIZER_ENABLE BIT(11)
+#define GPMI_ECCCTRL_RANDOMIZER_TYPE0 0
+#define GPMI_ECCCTRL_RANDOMIZER_TYPE1 (1 << 9)
+#define GPMI_ECCCTRL_RANDOMIZER_TYPE2 (2 << 9)
+#define GPMI_ECCCTRL_ENABLE_ECC BIT(12)
+#define GPMI_ECCCTRL_BUFFER_MASK GENMASK(8, 0)
+#define GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY 0x100
+#define GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE 0x1ff
+
+#define GPMI_STAT 0x000000b0
+#define GPMI_STAT_READY_BUSY_OFFSET 24
+
+#define GPMI_DEBUG 0x000000c0
+#define GPMI_DEBUG_READY0_OFFSET 28
+
+#define GPMI_VERSION 0x000000d0
+#define GPMI_VERSION_MINOR_OFFSET 16
+#define GPMI_VERSION_TYPE_MX23 0x0300
+
+#define BCH_CTRL 0x00000000
+#define BCH_CTRL_COMPLETE_IRQ BIT(0)
+#define BCH_CTRL_COMPLETE_IRQ_EN BIT(8)
+
+#define BCH_LAYOUTSELECT 0x00000070
+
+#define BCH_FLASH0LAYOUT0 0x00000080
+#define BCH_FLASHLAYOUT0_NBLOCKS GENMASK(31, 24)
+#define BCH_FLASHLAYOUT0_META_SIZE GENMASK(23, 16)
+#define BCH_FLASHLAYOUT0_ECC0 GENMASK(15, 12)
+#define IMX6_BCH_FLASHLAYOUT0_ECC0 GENMASK(15, 11)
+#define BCH_FLASHLAYOUT0_DATA0_SIZE GENMASK(9, 0)
+#define BCH_FLASHLAYOUT0_GF13_0_GF14_1 BIT(10)
+
+#define BCH_FLASH0LAYOUT1 0x00000090
+#define BCH_FLASHLAYOUT1_PAGE_SIZE GENMASK(31, 16)
+#define BCH_FLASHLAYOUT1_ECCN GENMASK(15, 12)
+#define IMX6_BCH_FLASHLAYOUT1_ECCN GENMASK(15, 11)
+#define BCH_FLASHLAYOUT1_GF13_0_GF14_1 BIT(10)
+#define BCH_FLASHLAYOUT1_DATAN_SIZE GENMASK(9, 0)
+
+#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
+
+#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
+#define MXS_NAND_METADATA_SIZE 10
+
+#define MXS_NAND_COMMAND_BUFFER_SIZE 32
+
+#define MXS_NAND_BCH_TIMEOUT 10000
+
+#endif /* __SOC_IMX_GPMI_NAND_H */
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 01/14] mtd: nand: nand-mxs: Move register definitions to separate file
2022-11-01 15:30 ` [PATCH 01/14] mtd: nand: nand-mxs: Move register definitions to separate file Sascha Hauer
@ 2022-11-02 8:08 ` Marco Felsch
0 siblings, 0 replies; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 8:08 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
Hi Sascha,
On 22-11-01, Sascha Hauer wrote:
> The GPMI registers are needed in the MTD GPMI driver and also in the
> xload-gpmi driver. So far both use their own set of register defines.
> Move the MTD GPMI register defines to include/ so that we can use them
> in the xload driver as well.
Nit: Should we note that we are replacing the manual bitops by
FIELD_PREP?
Regards,
Marco
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/mtd/nand/nand_mxs.c | 186 ++++++------------------------------
> include/soc/imx/gpmi-nand.h | 114 ++++++++++++++++++++++
> 2 files changed, 145 insertions(+), 155 deletions(-)
> create mode 100644 include/soc/imx/gpmi-nand.h
>
> diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
> index 5faa17a4bd..d711708ff2 100644
> --- a/drivers/mtd/nand/nand_mxs.c
> +++ b/drivers/mtd/nand/nand_mxs.c
> @@ -21,6 +21,7 @@
> #include <linux/types.h>
> #include <linux/clk.h>
> #include <linux/err.h>
> +#include <linux/bitfield.h>
> #include <of_mtd.h>
> #include <common.h>
> #include <dma.h>
> @@ -32,139 +33,10 @@
> #include <dma/apbh-dma.h>
> #include <stmp-device.h>
> #include <mach/generic.h>
> +#include <soc/imx/gpmi-nand.h>
>
> #include "internals.h"
>
> -#define MX28_BLOCK_SFTRST (1 << 31)
> -#define MX28_BLOCK_CLKGATE (1 << 30)
> -
> -#define GPMI_CTRL0 0x00000000
> -#define GPMI_CTRL0_RUN (1 << 29)
> -#define GPMI_CTRL0_DEV_IRQ_EN (1 << 28)
> -/* Disable for now since we don't need it and it is different on MX23.
> -#define GPMI_CTRL0_LOCK_CS (1 << 27)
> -*/
> -#define GPMI_CTRL0_UDMA (1 << 26)
> -#define GPMI_CTRL0_COMMAND_MODE_MASK (0x3 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_OFFSET 24
> -#define GPMI_CTRL0_COMMAND_MODE_WRITE (0x0 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_READ (0x1 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE (0x2 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY (0x3 << 24)
> -#define GPMI_CTRL0_WORD_LENGTH (1 << 23)
> -/* Careful: Is 0x3 on MX23
> -#define GPMI_CTRL0_CS_MASK (0x7 << 20)
> -*/
> -#define GPMI_CTRL0_CS_OFFSET 20
> -#define GPMI_CTRL0_ADDRESS_MASK (0x7 << 17)
> -#define GPMI_CTRL0_ADDRESS_OFFSET 17
> -#define GPMI_CTRL0_ADDRESS_NAND_DATA (0x0 << 17)
> -#define GPMI_CTRL0_ADDRESS_NAND_CLE (0x1 << 17)
> -#define GPMI_CTRL0_ADDRESS_NAND_ALE (0x2 << 17)
> -#define GPMI_CTRL0_ADDRESS_INCREMENT (1 << 16)
> -#define GPMI_CTRL0_XFER_COUNT_MASK 0xffff
> -#define GPMI_CTRL0_XFER_COUNT_OFFSET 0
> -
> -#define GPMI_CTRL1 0x00000060
> -#define GPMI_CTRL1_SET 0x00000064
> -#define GPMI_CTRL1_CLR 0x00000068
> -#define GPMI_CTRL1_DECOUPLE_CS (1 << 24)
> -#define GPMI_CTRL1_WRN_DLY(d) (((d) & 0x3) << 22)
> -#define GPMI_CTRL1_TIMEOUT_IRQ_EN (1 << 20)
> -#define GPMI_CTRL1_GANGED_RDYBUSY (1 << 19)
> -#define GPMI_CTRL1_BCH_MODE (1 << 18)
> -#define GPMI_CTRL1_DLL_ENABLE (1 << 17)
> -#define GPMI_CTRL1_HALF_PERIOD (1 << 16)
> -#define GPMI_CTRL1_RDN_DELAY(d) (((d) & 0xf) << 12)
> -#define GPMI_CTRL1_DMA2ECC_MODE (1 << 11)
> -#define GPMI_CTRL1_DEV_IRQ (1 << 10)
> -#define GPMI_CTRL1_TIMEOUT_IRQ (1 << 9)
> -#define GPMI_CTRL1_BURST_EN (1 << 8)
> -#define GPMI_CTRL1_ABORT_WAIT_REQUEST (1 << 7)
> -#define GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_MASK (0x7 << 4)
> -#define GPMI_CTRL1_ABORT_WAIT_FOR_READY_CHANNEL_OFFSET 4
> -#define GPMI_CTRL1_DEV_RESET (1 << 3)
> -#define GPMI_CTRL1_ATA_IRQRDY_POLARITY (1 << 2)
> -#define GPMI_CTRL1_CAMERA_MODE (1 << 1)
> -#define GPMI_CTRL1_GPMI_MODE (1 << 0)
> -
> -#define BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS 0x0
> -#define BV_GPMI_CTRL1_WRN_DLY_SEL_6_TO_10NS 0x1
> -#define BV_GPMI_CTRL1_WRN_DLY_SEL_7_TO_12NS 0x2
> -#define BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY 0x3
> -
> -#define GPMI_TIMING0 0x00000070
> -
> -#define GPMI_TIMING0_ADDRESS_SETUP(d) (((d) & 0xff) << 16)
> -#define GPMI_TIMING0_DATA_HOLD(d) (((d) & 0xff) << 8)
> -#define GPMI_TIMING0_DATA_SETUP(d) (((d) & 0xff) << 0)
> -
> -#define GPMI_TIMING1 0x00000080
> -#define GPMI_TIMING1_BUSY_TIMEOUT(d) (((d) & 0xffff) << 16)
> -
> -#define GPMI_ECCCTRL_HANDLE_MASK (0xffff << 16)
> -#define GPMI_ECCCTRL_HANDLE_OFFSET 16
> -#define GPMI_ECCCTRL_ECC_CMD_MASK (0x3 << 13)
> -#define GPMI_ECCCTRL_ECC_CMD_OFFSET 13
> -#define GPMI_ECCCTRL_ECC_CMD_DECODE (0x0 << 13)
> -#define GPMI_ECCCTRL_ECC_CMD_ENCODE (0x1 << 13)
> -#define GPMI_ECCCTRL_RANDOMIZER_ENABLE (1 << 11)
> -#define GPMI_ECCCTRL_RANDOMIZER_TYPE0 0
> -#define GPMI_ECCCTRL_RANDOMIZER_TYPE1 (1 << 9)
> -#define GPMI_ECCCTRL_RANDOMIZER_TYPE2 (2 << 9)
> -#define GPMI_ECCCTRL_ENABLE_ECC (1 << 12)
> -#define GPMI_ECCCTRL_BUFFER_MASK_MASK 0x1ff
> -#define GPMI_ECCCTRL_BUFFER_MASK_OFFSET 0
> -#define GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY 0x100
> -#define GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE 0x1ff
> -
> -#define GPMI_STAT 0x000000b0
> -#define GPMI_STAT_READY_BUSY_OFFSET 24
> -
> -#define GPMI_DEBUG 0x000000c0
> -#define GPMI_DEBUG_READY0_OFFSET 28
> -
> -#define GPMI_VERSION 0x000000d0
> -#define GPMI_VERSION_MINOR_OFFSET 16
> -#define GPMI_VERSION_TYPE_MX23 0x0300
> -
> -#define BCH_CTRL 0x00000000
> -#define BCH_CTRL_COMPLETE_IRQ (1 << 0)
> -#define BCH_CTRL_COMPLETE_IRQ_EN (1 << 8)
> -
> -#define BCH_LAYOUTSELECT 0x00000070
> -
> -#define BCH_FLASH0LAYOUT0 0x00000080
> -#define BCH_FLASHLAYOUT0_NBLOCKS_MASK (0xff << 24)
> -#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24
> -#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16)
> -#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16
> -#define BCH_FLASHLAYOUT0_ECC0_MASK (0xf << 12)
> -#define BCH_FLASHLAYOUT0_ECC0_OFFSET 12
> -#define IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET 11
> -#define BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET 0
> -#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_MASK BIT(10)
> -#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET 10
> -
> -#define BCH_FLASH0LAYOUT1 0x00000090
> -#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16)
> -#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16
> -#define BCH_FLASHLAYOUT1_ECCN_MASK (0xf << 12)
> -#define BCH_FLASHLAYOUT1_ECCN_OFFSET 12
> -#define IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET 11
> -#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK BIT(10)
> -#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET 10
> -#define BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET 0
> -
> -#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
> -
> -#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
> -#define MXS_NAND_METADATA_SIZE 10
> -
> -#define MXS_NAND_COMMAND_BUFFER_SIZE 32
> -
> -#define MXS_NAND_BCH_TIMEOUT 10000
> -
> enum gpmi_type {
> GPMI_MXS,
> GPMI_IMX6,
> @@ -503,7 +375,7 @@ static void mxs_nand_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctr
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> nand_info->cmd_queue_len;
> @@ -634,7 +506,7 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> length;
>
> @@ -659,7 +531,7 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_DATA;
>
> mxs_dma_desc_append(channel, d);
> @@ -713,7 +585,7 @@ static void mxs_nand_write_buf(struct nand_chip *chip, const uint8_t *buf,
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> length;
>
> @@ -749,16 +621,22 @@ static void mxs_nand_config_bch(struct nand_chip *chip, int readlen)
> else
> chunk_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
>
> - fl0 = (mxs_nand_ecc_chunk_cnt(readlen) - 1)
> - << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> - fl0 |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> - fl0 |= (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET;
> - fl0 |= chunk_size;
> + fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, mxs_nand_ecc_chunk_cnt(readlen) - 1);
> + fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, MXS_NAND_METADATA_SIZE);
> + if (mxs_nand_is_imx6(nand_info))
> + fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, chip->ecc.strength >> 1);
> + else
> + fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_ECC0, chip->ecc.strength >> 1);
> + fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, chunk_size);
> writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
>
> - fl1 = readlen << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> - fl1 |= (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET;
> - fl1 |= chunk_size;
> + fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, readlen);
> + if (mxs_nand_is_imx6(nand_info))
> + fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, chip->ecc.strength >> 1);
> + else
> + fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_ECCN, chip->ecc.strength >> 1);
> +
> + fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, chunk_size);
> writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
> }
>
> @@ -781,7 +659,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_DATA;
>
> mxs_dma_desc_append(channel, d);
> @@ -797,7 +675,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> readtotal;
> d->cmd.pio_words[1] = 0;
> @@ -829,7 +707,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> readtotal;
> d->cmd.pio_words[1] = 0;
> @@ -1037,7 +915,7 @@ static int mxs_nand_ecc_write_page(struct nand_chip *chip, const uint8_t *buf,
> d->cmd.pio_words[0] =
> GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - (nand_info->cur_chip << GPMI_CTRL0_CS_OFFSET) |
> + FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
> GPMI_CTRL0_ADDRESS_NAND_DATA;
> d->cmd.pio_words[1] = 0;
> d->cmd.pio_words[2] =
> @@ -1276,23 +1154,21 @@ static void mxs_nand_mode_fcb_62bit(struct mxs_nand_info *nand_info)
> bch_regs = nand_info->bch_base;
>
> /* 8 ecc_chunks */
> - fl0 = 7 << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> + fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, 7);
> /* 32 bytes for metadata */
> - fl0 |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> + fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, 32);
> /* using ECC62 level to be performed */
> - fl0 |= 0x1F << IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET;
> + fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, 0x1f);
> /* 0x20 * 4 bytes of the data0 block */
> - fl0 |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
> - fl0 |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
> + fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, 0x20);
> writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
>
> /* 1024 for data + 838 for OOB */
> - fl1 = BCH62_PAGESIZE << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> + fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, BCH62_PAGESIZE);
> /* using ECC62 level to be performed */
> - fl1 |= 0x1f << IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET;
> + fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, 0x1f);
> /* 0x20 * 4 bytes of the data0 block */
> - fl1 |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
> - fl1 |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
> + fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, 0x20);
> writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
> }
>
> diff --git a/include/soc/imx/gpmi-nand.h b/include/soc/imx/gpmi-nand.h
> new file mode 100644
> index 0000000000..f7a2caa1d6
> --- /dev/null
> +++ b/include/soc/imx/gpmi-nand.h
> @@ -0,0 +1,114 @@
> +#ifndef __SOC_IMX_GPMI_NAND_H
> +#define __SOC_IMX_GPMI_NAND_H
> +
> +#include <linux/bitfield.h>
> +
> +#define GPMI_CTRL0 0x00000000
> +#define GPMI_CTRL0_SFTRST BIT(31)
> +#define GPMI_CTRL0_RUN BIT(29)
> +#define GPMI_CTRL0_DEV_IRQ_EN BIT(28)
> +#define GPMI_CTRL0_UDMA BIT(26)
> +#define GPMI_CTRL0_COMMAND_MODE GENMASK(25, 24)
> +#define GPMI_CTRL0_COMMAND_MODE_WRITE (0x0 << 24)
> +#define GPMI_CTRL0_COMMAND_MODE_READ (0x1 << 24)
> +#define GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE (0x2 << 24)
> +#define GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY (0x3 << 24)
> +#define GPMI_CTRL0_WORD_LENGTH (1 << 23)
> +#define GPMI_CTRL0_CS GENMASK(22, 20)
> +#define GPMI_CTRL0_ADDRESS GENMASK(19, 17)
> +#define GPMI_CTRL0_ADDRESS_NAND_DATA (0x0 << 17)
> +#define GPMI_CTRL0_ADDRESS_NAND_CLE (0x1 << 17)
> +#define GPMI_CTRL0_ADDRESS_NAND_ALE (0x2 << 17)
> +#define GPMI_CTRL0_ADDRESS_INCREMENT BIT(16)
> +#define GPMI_CTRL0_XFER_COUNT GENMASK(15, 0)
> +
> +#define GPMI_CTRL1 0x00000060
> +#define GPMI_CTRL1_SET 0x00000064
> +#define GPMI_CTRL1_CLR 0x00000068
> +#define GPMI_CTRL1_DECOUPLE_CS BIT(24)
> +#define GPMI_CTRL1_WRN_DLY(d) (((d) & 0x3) << 22)
> +#define GPMI_CTRL1_TIMEOUT_IRQ_EN BIT(20)
> +#define GPMI_CTRL1_GANGED_RDYBUSY BIT(19)
> +#define GPMI_CTRL1_BCH_MODE BIT(18)
> +#define GPMI_CTRL1_DLL_ENABLE BIT(17)
> +#define GPMI_CTRL1_HALF_PERIOD BIT(16)
> +#define GPMI_CTRL1_RDN_DELAY(d) (((d) & 0xf) << 12)
> +#define GPMI_CTRL1_DMA2ECC_MODE BIT(11)
> +#define GPMI_CTRL1_DEV_IRQ BIT(10)
> +#define GPMI_CTRL1_TIMEOUT_IRQ BIT(9)
> +#define GPMI_CTRL1_BURST_EN BIT(8)
> +#define GPMI_CTRL1_ABORT_WAIT_REQUEST BIT(7)
> +#define GPMI_CTRL1_ABORT_WAIT_FOR_READY GENMASK(6, 4)
> +#define GPMI_CTRL1_DEV_RESET BIT(3)
> +#define GPMI_CTRL1_ATA_IRQRDY_POLARITY BIT(2)
> +#define GPMI_CTRL1_CAMERA_MODE BIT(1)
> +#define GPMI_CTRL1_GPMI_MODE BIT(0)
> +
> +#define BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS 0x0
> +#define BV_GPMI_CTRL1_WRN_DLY_SEL_6_TO_10NS 0x1
> +#define BV_GPMI_CTRL1_WRN_DLY_SEL_7_TO_12NS 0x2
> +#define BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY 0x3
> +
> +#define GPMI_TIMING0 0x00000070
> +
> +#define GPMI_TIMING0_ADDRESS_SETUP(d) (((d) & 0xff) << 16)
> +#define GPMI_TIMING0_DATA_HOLD(d) (((d) & 0xff) << 8)
> +#define GPMI_TIMING0_DATA_SETUP(d) (((d) & 0xff) << 0)
> +
> +#define GPMI_TIMING1 0x00000080
> +#define GPMI_TIMING1_BUSY_TIMEOUT(d) (((d) & 0xffff) << 16)
> +
> +#define GPMI_ECCCTRL_HANDLE GENMASK(31, 16)
> +#define GPMI_ECCCTRL_ECC_CMD GENMASK(14, 13)
> +#define GPMI_ECCCTRL_ECC_CMD_DECODE (0x0 << 13)
> +#define GPMI_ECCCTRL_ECC_CMD_ENCODE (0x1 << 13)
> +#define GPMI_ECCCTRL_RANDOMIZER_ENABLE BIT(11)
> +#define GPMI_ECCCTRL_RANDOMIZER_TYPE0 0
> +#define GPMI_ECCCTRL_RANDOMIZER_TYPE1 (1 << 9)
> +#define GPMI_ECCCTRL_RANDOMIZER_TYPE2 (2 << 9)
> +#define GPMI_ECCCTRL_ENABLE_ECC BIT(12)
> +#define GPMI_ECCCTRL_BUFFER_MASK GENMASK(8, 0)
> +#define GPMI_ECCCTRL_BUFFER_MASK_BCH_AUXONLY 0x100
> +#define GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE 0x1ff
> +
> +#define GPMI_STAT 0x000000b0
> +#define GPMI_STAT_READY_BUSY_OFFSET 24
> +
> +#define GPMI_DEBUG 0x000000c0
> +#define GPMI_DEBUG_READY0_OFFSET 28
> +
> +#define GPMI_VERSION 0x000000d0
> +#define GPMI_VERSION_MINOR_OFFSET 16
> +#define GPMI_VERSION_TYPE_MX23 0x0300
> +
> +#define BCH_CTRL 0x00000000
> +#define BCH_CTRL_COMPLETE_IRQ BIT(0)
> +#define BCH_CTRL_COMPLETE_IRQ_EN BIT(8)
> +
> +#define BCH_LAYOUTSELECT 0x00000070
> +
> +#define BCH_FLASH0LAYOUT0 0x00000080
> +#define BCH_FLASHLAYOUT0_NBLOCKS GENMASK(31, 24)
> +#define BCH_FLASHLAYOUT0_META_SIZE GENMASK(23, 16)
> +#define BCH_FLASHLAYOUT0_ECC0 GENMASK(15, 12)
> +#define IMX6_BCH_FLASHLAYOUT0_ECC0 GENMASK(15, 11)
> +#define BCH_FLASHLAYOUT0_DATA0_SIZE GENMASK(9, 0)
> +#define BCH_FLASHLAYOUT0_GF13_0_GF14_1 BIT(10)
> +
> +#define BCH_FLASH0LAYOUT1 0x00000090
> +#define BCH_FLASHLAYOUT1_PAGE_SIZE GENMASK(31, 16)
> +#define BCH_FLASHLAYOUT1_ECCN GENMASK(15, 12)
> +#define IMX6_BCH_FLASHLAYOUT1_ECCN GENMASK(15, 11)
> +#define BCH_FLASHLAYOUT1_GF13_0_GF14_1 BIT(10)
> +#define BCH_FLASHLAYOUT1_DATAN_SIZE GENMASK(9, 0)
> +
> +#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4
> +
> +#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
> +#define MXS_NAND_METADATA_SIZE 10
> +
> +#define MXS_NAND_COMMAND_BUFFER_SIZE 32
> +
> +#define MXS_NAND_BCH_TIMEOUT 10000
> +
> +#endif /* __SOC_IMX_GPMI_NAND_H */
> --
> 2.30.2
>
>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 02/14] ARM: i.MX: xload nand: Use common register defines
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
2022-11-01 15:30 ` [PATCH 01/14] mtd: nand: nand-mxs: Move register definitions to separate file Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-02 8:10 ` Marco Felsch
2022-11-01 15:30 ` [PATCH 03/14] ARM: i.MX: xload nand: add common readid Sascha Hauer
` (11 subsequent siblings)
13 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
We have a set of GPMI register defines in include/, so use them for the
xload driver as well.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/xload-gpmi-nand.c | 66 ++++++++---------------------
1 file changed, 17 insertions(+), 49 deletions(-)
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 3a4f331ce6..6ac9af762f 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -11,6 +11,7 @@
#include <mach/xload.h>
#include <soc/imx/imx-nand-bcb.h>
#include <linux/mtd/rawnand.h>
+#include <soc/imx/gpmi-nand.h>
#include <mach/imx6-regs.h>
#include <mach/clock-imx6.h>
@@ -203,39 +204,6 @@ static int mxs_dma_run(struct mxs_dma_chan *pchan, struct mxs_dma_cmd *pdesc,
/* ----------------------------- NAND driver part -------------------------- */
-#define GPMI_CTRL0 0x00000000
-#define GPMI_CTRL0_RUN (1 << 29)
-#define GPMI_CTRL0_DEV_IRQ_EN (1 << 28)
-#define GPMI_CTRL0_UDMA (1 << 26)
-#define GPMI_CTRL0_COMMAND_MODE_MASK (0x3 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_OFFSET 24
-#define GPMI_CTRL0_COMMAND_MODE_WRITE (0x0 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_READ (0x1 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE (0x2 << 24)
-#define GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY (0x3 << 24)
-#define GPMI_CTRL0_WORD_LENGTH (1 << 23)
-#define GPMI_CTRL0_CS(cs) ((cs) << 20)
-#define GPMI_CTRL0_ADDRESS_MASK (0x7 << 17)
-#define GPMI_CTRL0_ADDRESS_OFFSET 17
-#define GPMI_CTRL0_ADDRESS_NAND_DATA (0x0 << 17)
-#define GPMI_CTRL0_ADDRESS_NAND_CLE (0x1 << 17)
-#define GPMI_CTRL0_ADDRESS_NAND_ALE (0x2 << 17)
-#define GPMI_CTRL0_ADDRESS_INCREMENT (1 << 16)
-#define GPMI_CTRL0_XFER_COUNT_MASK 0xffff
-#define GPMI_CTRL0_XFER_COUNT_OFFSET 0
-
-#define GPMI_ECCCTRL_ECC_CMD_DECODE (0x0 << 13)
-#define GPMI_ECCCTRL_ENABLE_ECC (1 << 12)
-#define GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE 0x1ff
-
-#define BCH_CTRL 0x00000000
-#define BCH_CTRL_COMPLETE_IRQ (1 << 0)
-
-#define MXS_NAND_DMA_DESCRIPTOR_COUNT 6
-#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
-#define MXS_NAND_METADATA_SIZE 10
-#define MXS_NAND_COMMAND_BUFFER_SIZE 128
-
struct mxs_nand_info {
void __iomem *io_base;
void __iomem *bch_base;
@@ -352,7 +320,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
cmd_queue_len;
@@ -372,7 +340,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
cmd_queue_len;
@@ -386,7 +354,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
if (raw) {
@@ -398,7 +366,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
DMACMD_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
(writesize + oobsize);
d->address = (dma_addr_t)databuf;
@@ -408,7 +376,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
d->data = DMACMD_WAIT4END | DMACMD_PIO_WORDS(6);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
(writesize + oobsize);
d->pio_words[1] = 0;
@@ -426,7 +394,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
DMACMD_PIO_WORDS(3);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
(writesize + oobsize);
}
@@ -499,7 +467,7 @@ static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
cmd_queue_len;
@@ -512,7 +480,7 @@ static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
DMACMD_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
(1);
d->address = (dma_addr_t)databuf;
@@ -557,7 +525,7 @@ static int mxs_nand_reset(struct mxs_nand_info *info, void *databuf)
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
cmd_queue_len;
@@ -629,7 +597,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
cmd_queue_len;
@@ -643,7 +611,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
/* Compile DMA descriptor - read. */
@@ -654,7 +622,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
DMACMD_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
(sizeof(struct nand_onfi_params));
d->address = (dma_addr_t)databuf;
@@ -733,7 +701,7 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
cmd_queue_len;
@@ -746,7 +714,7 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
DMACMD_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
(sizeof(struct onfi_header));
d->address = (dma_addr_t)databuf;
@@ -811,7 +779,7 @@ static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_CLE |
GPMI_CTRL0_ADDRESS_INCREMENT |
cmd_queue_len;
@@ -824,7 +792,7 @@ static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
DMACMD_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
- GPMI_CTRL0_CS(info->cs) |
+ FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
(sizeof(struct readid_data));
d->address = (dma_addr_t)databuf;
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 02/14] ARM: i.MX: xload nand: Use common register defines
2022-11-01 15:30 ` [PATCH 02/14] ARM: i.MX: xload nand: Use common register defines Sascha Hauer
@ 2022-11-02 8:10 ` Marco Felsch
0 siblings, 0 replies; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 8:10 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
Hi Sascha,
On 22-11-01, Sascha Hauer wrote:
> We have a set of GPMI register defines in include/, so use them for the
> xload driver as well.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/mach-imx/xload-gpmi-nand.c | 66 ++++++++---------------------
> 1 file changed, 17 insertions(+), 49 deletions(-)
>
> diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
> index 3a4f331ce6..6ac9af762f 100644
> --- a/arch/arm/mach-imx/xload-gpmi-nand.c
> +++ b/arch/arm/mach-imx/xload-gpmi-nand.c
> @@ -11,6 +11,7 @@
> #include <mach/xload.h>
> #include <soc/imx/imx-nand-bcb.h>
> #include <linux/mtd/rawnand.h>
> +#include <soc/imx/gpmi-nand.h>
> #include <mach/imx6-regs.h>
> #include <mach/clock-imx6.h>
missing bitfield.h include.
Also should we say in the commit message that we are using the
FIELD_PREP now by this change?
Regards,
Marco
>
> @@ -203,39 +204,6 @@ static int mxs_dma_run(struct mxs_dma_chan *pchan, struct mxs_dma_cmd *pdesc,
>
> /* ----------------------------- NAND driver part -------------------------- */
>
> -#define GPMI_CTRL0 0x00000000
> -#define GPMI_CTRL0_RUN (1 << 29)
> -#define GPMI_CTRL0_DEV_IRQ_EN (1 << 28)
> -#define GPMI_CTRL0_UDMA (1 << 26)
> -#define GPMI_CTRL0_COMMAND_MODE_MASK (0x3 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_OFFSET 24
> -#define GPMI_CTRL0_COMMAND_MODE_WRITE (0x0 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_READ (0x1 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE (0x2 << 24)
> -#define GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY (0x3 << 24)
> -#define GPMI_CTRL0_WORD_LENGTH (1 << 23)
> -#define GPMI_CTRL0_CS(cs) ((cs) << 20)
> -#define GPMI_CTRL0_ADDRESS_MASK (0x7 << 17)
> -#define GPMI_CTRL0_ADDRESS_OFFSET 17
> -#define GPMI_CTRL0_ADDRESS_NAND_DATA (0x0 << 17)
> -#define GPMI_CTRL0_ADDRESS_NAND_CLE (0x1 << 17)
> -#define GPMI_CTRL0_ADDRESS_NAND_ALE (0x2 << 17)
> -#define GPMI_CTRL0_ADDRESS_INCREMENT (1 << 16)
> -#define GPMI_CTRL0_XFER_COUNT_MASK 0xffff
> -#define GPMI_CTRL0_XFER_COUNT_OFFSET 0
> -
> -#define GPMI_ECCCTRL_ECC_CMD_DECODE (0x0 << 13)
> -#define GPMI_ECCCTRL_ENABLE_ECC (1 << 12)
> -#define GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE 0x1ff
> -
> -#define BCH_CTRL 0x00000000
> -#define BCH_CTRL_COMPLETE_IRQ (1 << 0)
> -
> -#define MXS_NAND_DMA_DESCRIPTOR_COUNT 6
> -#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512
> -#define MXS_NAND_METADATA_SIZE 10
> -#define MXS_NAND_COMMAND_BUFFER_SIZE 128
> -
> struct mxs_nand_info {
> void __iomem *io_base;
> void __iomem *bch_base;
> @@ -352,7 +320,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> cmd_queue_len;
> @@ -372,7 +340,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> cmd_queue_len;
> @@ -386,7 +354,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA;
>
> if (raw) {
> @@ -398,7 +366,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> DMACMD_COMMAND_DMA_WRITE;
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> (writesize + oobsize);
> d->address = (dma_addr_t)databuf;
> @@ -408,7 +376,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> d->data = DMACMD_WAIT4END | DMACMD_PIO_WORDS(6);
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> (writesize + oobsize);
> d->pio_words[1] = 0;
> @@ -426,7 +394,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> DMACMD_PIO_WORDS(3);
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> (writesize + oobsize);
> }
> @@ -499,7 +467,7 @@ static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> cmd_queue_len;
> @@ -512,7 +480,7 @@ static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
> DMACMD_COMMAND_DMA_WRITE;
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> (1);
> d->address = (dma_addr_t)databuf;
> @@ -557,7 +525,7 @@ static int mxs_nand_reset(struct mxs_nand_info *info, void *databuf)
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> cmd_queue_len;
> @@ -629,7 +597,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> cmd_queue_len;
> @@ -643,7 +611,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA;
>
> /* Compile DMA descriptor - read. */
> @@ -654,7 +622,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
> DMACMD_COMMAND_DMA_WRITE;
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> (sizeof(struct nand_onfi_params));
> d->address = (dma_addr_t)databuf;
> @@ -733,7 +701,7 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> cmd_queue_len;
> @@ -746,7 +714,7 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
> DMACMD_COMMAND_DMA_WRITE;
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> (sizeof(struct onfi_header));
> d->address = (dma_addr_t)databuf;
> @@ -811,7 +779,7 @@ static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
>
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_CLE |
> GPMI_CTRL0_ADDRESS_INCREMENT |
> cmd_queue_len;
> @@ -824,7 +792,7 @@ static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
> DMACMD_COMMAND_DMA_WRITE;
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> - GPMI_CTRL0_CS(info->cs) |
> + FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> (sizeof(struct readid_data));
> d->address = (dma_addr_t)databuf;
> --
> 2.30.2
>
>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 03/14] ARM: i.MX: xload nand: add common readid
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
2022-11-01 15:30 ` [PATCH 01/14] mtd: nand: nand-mxs: Move register definitions to separate file Sascha Hauer
2022-11-01 15:30 ` [PATCH 02/14] ARM: i.MX: xload nand: Use common register defines Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-02 8:23 ` Marco Felsch
2022-11-01 15:30 ` [PATCH 04/14] dma: apbh-dma: Simplify code Sascha Hauer
` (10 subsequent siblings)
13 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
mxs_nand_check_onfi() and mxs_nand_read_id() setup the same DMA
descriptors with only a small difference. factor out a common
read_id function from it and share the code.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/xload-gpmi-nand.c | 148 ++++++++++------------------
1 file changed, 54 insertions(+), 94 deletions(-)
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 6ac9af762f..ffbd5c22e3 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -668,7 +668,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
return ret;
}
-static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
+static int mxs_nand_read_id(struct mxs_nand_info *info, u8 adr, void *databuf, size_t len)
{
int ret;
u8 *cmd_buf;
@@ -676,13 +676,6 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
int descnum = 0;
int cmd_queue_len;
- struct onfi_header {
- u8 byte0;
- u8 byte1;
- u8 byte2;
- u8 byte3;
- } onfi_head;
-
memset(info->desc, 0,
sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
@@ -692,7 +685,7 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
d = &info->desc[descnum++];
d->address = (dma_addr_t)(cmd_buf);
cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
- cmd_buf[cmd_queue_len++] = 0x20;
+ cmd_buf[cmd_queue_len++] = adr;
d->data = DMACMD_COMMAND_DMA_READ |
DMACMD_WAIT4END |
@@ -710,13 +703,13 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
d = &info->desc[descnum++];
d->data = DMACMD_WAIT4END |
DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(sizeof(struct onfi_header)) |
+ DMACMD_XFER_COUNT(len) |
DMACMD_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
- (sizeof(struct onfi_header));
+ len;
d->address = (dma_addr_t)databuf;
/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
@@ -725,119 +718,86 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
/* Execute the DMA chain. */
ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
- if (ret) {
+ if (ret)
pr_err("DMA read error\n");
- return ret;
- }
- memcpy(&onfi_head, databuf, sizeof(struct onfi_header));
+ return ret;
+}
+
+struct onfi_header {
+ u8 byte0;
+ u8 byte1;
+ u8 byte2;
+ u8 byte3;
+};
+
+static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
+{
+ int ret;
+ struct onfi_header *onfi_head = databuf;
+
+ ret = mxs_nand_read_id(info, 0x20, databuf, sizeof(struct onfi_header));
+ if (ret)
+ return ret;
- pr_debug("ONFI Byte0: 0x%x\n", onfi_head.byte0);
- pr_debug("ONFI Byte1: 0x%x\n", onfi_head.byte1);
- pr_debug("ONFI Byte2: 0x%x\n", onfi_head.byte2);
- pr_debug("ONFI Byte3: 0x%x\n", onfi_head.byte3);
+ pr_debug("ONFI Byte0: 0x%x\n", onfi_head->byte0);
+ pr_debug("ONFI Byte1: 0x%x\n", onfi_head->byte1);
+ pr_debug("ONFI Byte2: 0x%x\n", onfi_head->byte2);
+ pr_debug("ONFI Byte3: 0x%x\n", onfi_head->byte3);
/* check if returned values correspond to ascii characters "ONFI" */
- if (onfi_head.byte0 != 0x4f || onfi_head.byte1 != 0x4e ||
- onfi_head.byte2 != 0x46 || onfi_head.byte3 != 0x49)
+ if (onfi_head->byte0 != 0x4f || onfi_head->byte1 != 0x4e ||
+ onfi_head->byte2 != 0x46 || onfi_head->byte3 != 0x49)
return 1;
return 0;
}
+struct readid_data {
+ u8 byte0;
+ u8 byte1;
+ u8 byte2;
+ u8 byte3;
+ u8 byte4;
+} id_data;
+
static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
{
int ret;
- u8 *cmd_buf;
- struct mxs_dma_cmd *d;
- int descnum = 0;
- int cmd_queue_len;
-
- struct readid_data {
- u8 byte0;
- u8 byte1;
- u8 byte2;
- u8 byte3;
- u8 byte4;
- } id_data;
-
- memset(info->desc, 0,
- sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+ struct readid_data *id_data = databuf;
- /* Compile DMA descriptor - READID */
- cmd_buf = info->cmd_buf;
- cmd_queue_len = 0;
- d = &info->desc[descnum++];
- d->address = (dma_addr_t)(cmd_buf);
- cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
- cmd_buf[cmd_queue_len++] = 0x00;
-
- d->data = DMACMD_COMMAND_DMA_READ |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(cmd_queue_len);
-
- d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
- GPMI_CTRL0_WORD_LENGTH |
- FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
- GPMI_CTRL0_ADDRESS_NAND_CLE |
- GPMI_CTRL0_ADDRESS_INCREMENT |
- cmd_queue_len;
-
- /* Compile DMA descriptor - read. */
- d = &info->desc[descnum++];
- d->data = DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(sizeof(struct readid_data)) |
- DMACMD_COMMAND_DMA_WRITE;
- d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
- GPMI_CTRL0_WORD_LENGTH |
- FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
- GPMI_CTRL0_ADDRESS_NAND_DATA |
- (sizeof(struct readid_data));
- d->address = (dma_addr_t)databuf;
-
- /* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
- d = &info->desc[descnum++];
- d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
-
- /* Execute the DMA chain. */
- ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
- if (ret) {
- pr_err("DMA read error\n");
+ ret = mxs_nand_read_id(info, 0x0, databuf, sizeof(struct readid_data));
+ if (ret)
return ret;
- }
-
- memcpy(&id_data, databuf, sizeof(struct readid_data));
- pr_debug("NAND Byte0: 0x%x\n", id_data.byte0);
- pr_debug("NAND Byte1: 0x%x\n", id_data.byte1);
- pr_debug("NAND Byte2: 0x%x\n", id_data.byte2);
- pr_debug("NAND Byte3: 0x%x\n", id_data.byte3);
- pr_debug("NAND Byte4: 0x%x\n", id_data.byte4);
+ pr_debug("NAND Byte0: 0x%x\n", id_data->byte0);
+ pr_debug("NAND Byte1: 0x%x\n", id_data->byte1);
+ pr_debug("NAND Byte2: 0x%x\n", id_data->byte2);
+ pr_debug("NAND Byte3: 0x%x\n", id_data->byte3);
+ pr_debug("NAND Byte4: 0x%x\n", id_data->byte4);
- if (id_data.byte0 == 0xff || id_data.byte1 == 0xff ||
- id_data.byte2 == 0xff || id_data.byte3 == 0xff ||
- id_data.byte4 == 0xff) {
+ if (id_data->byte0 == 0xff || id_data->byte1 == 0xff ||
+ id_data->byte2 == 0xff || id_data->byte3 == 0xff ||
+ id_data->byte4 == 0xff) {
pr_err("\"READ ID\" returned 0xff, possible error!\n");
return -EOVERFLOW;
}
/* Fill the NAND organization struct with data */
info->organization.bits_per_cell =
- (1 << ((id_data.byte2 >> 2) & 0x3)) * 2;
+ (1 << ((id_data->byte2 >> 2) & 0x3)) * 2;
info->organization.pagesize =
- (1 << (id_data.byte3 & 0x3)) * SZ_1K;
- info->organization.oobsize = id_data.byte3 & 0x4 ?
+ (1 << (id_data->byte3 & 0x3)) * SZ_1K;
+ info->organization.oobsize = id_data->byte3 & 0x4 ?
info->organization.pagesize / 512 * 16 :
info->organization.pagesize / 512 * 8;
info->organization.pages_per_eraseblock =
- (1 << ((id_data.byte3 >> 4) & 0x3)) * SZ_64K /
+ (1 << ((id_data->byte3 >> 4) & 0x3)) * SZ_64K /
info->organization.pagesize;
info->organization.planes_per_lun =
- 1 << ((id_data.byte4 >> 2) & 0x3);
+ 1 << ((id_data->byte4 >> 2) & 0x3);
info->nand_size = info->organization.planes_per_lun *
- (1 << ((id_data.byte4 >> 4) & 0x7)) * SZ_8M;
+ (1 << ((id_data->byte4 >> 4) & 0x7)) * SZ_8M;
info->organization.eraseblocks_per_lun = info->nand_size /
(info->organization.pages_per_eraseblock *
info->organization.pagesize);
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 03/14] ARM: i.MX: xload nand: add common readid
2022-11-01 15:30 ` [PATCH 03/14] ARM: i.MX: xload nand: add common readid Sascha Hauer
@ 2022-11-02 8:23 ` Marco Felsch
0 siblings, 0 replies; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 8:23 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
Hi Sascha,
On 22-11-01, Sascha Hauer wrote:
> mxs_nand_check_onfi() and mxs_nand_read_id() setup the same DMA
> descriptors with only a small difference. factor out a common
> read_id function from it and share the code.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/mach-imx/xload-gpmi-nand.c | 148 ++++++++++------------------
> 1 file changed, 54 insertions(+), 94 deletions(-)
>
> diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
> index 6ac9af762f..ffbd5c22e3 100644
> --- a/arch/arm/mach-imx/xload-gpmi-nand.c
> +++ b/arch/arm/mach-imx/xload-gpmi-nand.c
> @@ -668,7 +668,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
> return ret;
> }
>
> -static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
> +static int mxs_nand_read_id(struct mxs_nand_info *info, u8 adr, void *databuf, size_t len)
> {
> int ret;
> u8 *cmd_buf;
> @@ -676,13 +676,6 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
> int descnum = 0;
> int cmd_queue_len;
>
> - struct onfi_header {
> - u8 byte0;
> - u8 byte1;
> - u8 byte2;
> - u8 byte3;
> - } onfi_head;
> -
> memset(info->desc, 0,
> sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
>
> @@ -692,7 +685,7 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
> d = &info->desc[descnum++];
> d->address = (dma_addr_t)(cmd_buf);
> cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
> - cmd_buf[cmd_queue_len++] = 0x20;
> + cmd_buf[cmd_queue_len++] = adr;
>
> d->data = DMACMD_COMMAND_DMA_READ |
> DMACMD_WAIT4END |
> @@ -710,13 +703,13 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
> d = &info->desc[descnum++];
> d->data = DMACMD_WAIT4END |
> DMACMD_PIO_WORDS(1) |
> - DMACMD_XFER_COUNT(sizeof(struct onfi_header)) |
> + DMACMD_XFER_COUNT(len) |
> DMACMD_COMMAND_DMA_WRITE;
> d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> GPMI_CTRL0_WORD_LENGTH |
> FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> GPMI_CTRL0_ADDRESS_NAND_DATA |
> - (sizeof(struct onfi_header));
> + len;
> d->address = (dma_addr_t)databuf;
>
> /* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
> @@ -725,119 +718,86 @@ static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
>
> /* Execute the DMA chain. */
> ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
> - if (ret) {
> + if (ret)
> pr_err("DMA read error\n");
> - return ret;
> - }
>
> - memcpy(&onfi_head, databuf, sizeof(struct onfi_header));
> + return ret;
> +}
> +
> +struct onfi_header {
> + u8 byte0;
> + u8 byte1;
> + u8 byte2;
> + u8 byte3;
> +};
> +
> +static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
> +{
> + int ret;
> + struct onfi_header *onfi_head = databuf;
> +
> + ret = mxs_nand_read_id(info, 0x20, databuf, sizeof(struct onfi_header));
> + if (ret)
> + return ret;
>
> - pr_debug("ONFI Byte0: 0x%x\n", onfi_head.byte0);
> - pr_debug("ONFI Byte1: 0x%x\n", onfi_head.byte1);
> - pr_debug("ONFI Byte2: 0x%x\n", onfi_head.byte2);
> - pr_debug("ONFI Byte3: 0x%x\n", onfi_head.byte3);
> + pr_debug("ONFI Byte0: 0x%x\n", onfi_head->byte0);
> + pr_debug("ONFI Byte1: 0x%x\n", onfi_head->byte1);
> + pr_debug("ONFI Byte2: 0x%x\n", onfi_head->byte2);
> + pr_debug("ONFI Byte3: 0x%x\n", onfi_head->byte3);
>
> /* check if returned values correspond to ascii characters "ONFI" */
> - if (onfi_head.byte0 != 0x4f || onfi_head.byte1 != 0x4e ||
> - onfi_head.byte2 != 0x46 || onfi_head.byte3 != 0x49)
> + if (onfi_head->byte0 != 0x4f || onfi_head->byte1 != 0x4e ||
> + onfi_head->byte2 != 0x46 || onfi_head->byte3 != 0x49)
Nit: Should we change the compare to something like this:
onfi_head->byte0 != 'O'
onfi_head->byte1 != 'N'
This way we can remove the comment.
> return 1;
>
> return 0;
> }
>
> +struct readid_data {
> + u8 byte0;
> + u8 byte1;
> + u8 byte2;
> + u8 byte3;
> + u8 byte4;
> +} id_data;
The id_data variable is unsused.
Regards,
Marco
> static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
> {
> int ret;
> - u8 *cmd_buf;
> - struct mxs_dma_cmd *d;
> - int descnum = 0;
> - int cmd_queue_len;
> -
> - struct readid_data {
> - u8 byte0;
> - u8 byte1;
> - u8 byte2;
> - u8 byte3;
> - u8 byte4;
> - } id_data;
> -
> - memset(info->desc, 0,
> - sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
> + struct readid_data *id_data = databuf;
>
> - /* Compile DMA descriptor - READID */
> - cmd_buf = info->cmd_buf;
> - cmd_queue_len = 0;
> - d = &info->desc[descnum++];
> - d->address = (dma_addr_t)(cmd_buf);
> - cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
> - cmd_buf[cmd_queue_len++] = 0x00;
> -
> - d->data = DMACMD_COMMAND_DMA_READ |
> - DMACMD_WAIT4END |
> - DMACMD_PIO_WORDS(1) |
> - DMACMD_XFER_COUNT(cmd_queue_len);
> -
> - d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
> - GPMI_CTRL0_WORD_LENGTH |
> - FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> - GPMI_CTRL0_ADDRESS_NAND_CLE |
> - GPMI_CTRL0_ADDRESS_INCREMENT |
> - cmd_queue_len;
> -
> - /* Compile DMA descriptor - read. */
> - d = &info->desc[descnum++];
> - d->data = DMACMD_WAIT4END |
> - DMACMD_PIO_WORDS(1) |
> - DMACMD_XFER_COUNT(sizeof(struct readid_data)) |
> - DMACMD_COMMAND_DMA_WRITE;
> - d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
> - GPMI_CTRL0_WORD_LENGTH |
> - FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
> - GPMI_CTRL0_ADDRESS_NAND_DATA |
> - (sizeof(struct readid_data));
> - d->address = (dma_addr_t)databuf;
> -
> - /* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
> - d = &info->desc[descnum++];
> - d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
> -
> - /* Execute the DMA chain. */
> - ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
> - if (ret) {
> - pr_err("DMA read error\n");
> + ret = mxs_nand_read_id(info, 0x0, databuf, sizeof(struct readid_data));
> + if (ret)
> return ret;
> - }
> -
> - memcpy(&id_data, databuf, sizeof(struct readid_data));
>
> - pr_debug("NAND Byte0: 0x%x\n", id_data.byte0);
> - pr_debug("NAND Byte1: 0x%x\n", id_data.byte1);
> - pr_debug("NAND Byte2: 0x%x\n", id_data.byte2);
> - pr_debug("NAND Byte3: 0x%x\n", id_data.byte3);
> - pr_debug("NAND Byte4: 0x%x\n", id_data.byte4);
> + pr_debug("NAND Byte0: 0x%x\n", id_data->byte0);
> + pr_debug("NAND Byte1: 0x%x\n", id_data->byte1);
> + pr_debug("NAND Byte2: 0x%x\n", id_data->byte2);
> + pr_debug("NAND Byte3: 0x%x\n", id_data->byte3);
> + pr_debug("NAND Byte4: 0x%x\n", id_data->byte4);
>
> - if (id_data.byte0 == 0xff || id_data.byte1 == 0xff ||
> - id_data.byte2 == 0xff || id_data.byte3 == 0xff ||
> - id_data.byte4 == 0xff) {
> + if (id_data->byte0 == 0xff || id_data->byte1 == 0xff ||
> + id_data->byte2 == 0xff || id_data->byte3 == 0xff ||
> + id_data->byte4 == 0xff) {
> pr_err("\"READ ID\" returned 0xff, possible error!\n");
> return -EOVERFLOW;
> }
>
> /* Fill the NAND organization struct with data */
> info->organization.bits_per_cell =
> - (1 << ((id_data.byte2 >> 2) & 0x3)) * 2;
> + (1 << ((id_data->byte2 >> 2) & 0x3)) * 2;
> info->organization.pagesize =
> - (1 << (id_data.byte3 & 0x3)) * SZ_1K;
> - info->organization.oobsize = id_data.byte3 & 0x4 ?
> + (1 << (id_data->byte3 & 0x3)) * SZ_1K;
> + info->organization.oobsize = id_data->byte3 & 0x4 ?
> info->organization.pagesize / 512 * 16 :
> info->organization.pagesize / 512 * 8;
> info->organization.pages_per_eraseblock =
> - (1 << ((id_data.byte3 >> 4) & 0x3)) * SZ_64K /
> + (1 << ((id_data->byte3 >> 4) & 0x3)) * SZ_64K /
> info->organization.pagesize;
> info->organization.planes_per_lun =
> - 1 << ((id_data.byte4 >> 2) & 0x3);
> + 1 << ((id_data->byte4 >> 2) & 0x3);
> info->nand_size = info->organization.planes_per_lun *
> - (1 << ((id_data.byte4 >> 4) & 0x7)) * SZ_8M;
> + (1 << ((id_data->byte4 >> 4) & 0x7)) * SZ_8M;
> info->organization.eraseblocks_per_lun = info->nand_size /
> (info->organization.pages_per_eraseblock *
> info->organization.pagesize);
> --
> 2.30.2
>
>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 04/14] dma: apbh-dma: Simplify code
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (2 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 03/14] ARM: i.MX: xload nand: add common readid Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-01 15:30 ` [PATCH 05/14] dma: apbh-dma: unify register defines Sascha Hauer
` (9 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
The apbh-dma driver supports chaining DMA descriptors while the DMA
engine is running. This is unused in barebox as well as in the Kernel.
We just queue one descriptor chain and wait for its completion, and
the MTD layer doesn't even support the more advanced features. Just
drop the unused code and greatly simplify it.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/dma/apbh_dma.c | 487 ++----------------------------------
drivers/mtd/nand/nand_mxs.c | 182 ++++++--------
include/dma/apbh-dma.h | 48 +---
3 files changed, 98 insertions(+), 619 deletions(-)
diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c
index 83bd783d34..e93bffd595 100644
--- a/drivers/dma/apbh_dma.c
+++ b/drivers/dma/apbh_dma.c
@@ -43,8 +43,6 @@
#define BM_APBHX_CHn_SEMA_PHORE (0xff << 16)
#define BP_APBHX_CHn_SEMA_PHORE 16
-static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS];
-
enum mxs_dma_id {
UNKNOWN_DMA_ID,
IMX23_DMA,
@@ -66,185 +64,9 @@ static struct apbh_dma *apbh_dma;
*/
static int mxs_dma_validate_chan(int channel)
{
- struct mxs_dma_chan *pchan;
-
if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
return -EINVAL;
- pchan = mxs_dma_channels + channel;
- if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
- return -EINVAL;
-
- return 0;
-}
-
-/*
- * Return the address of the command within a descriptor.
- */
-static unsigned int mxs_dma_cmd_address(struct mxs_dma_desc *desc)
-{
- return desc->address + offsetof(struct mxs_dma_desc, cmd);
-}
-
-/*
- * Read a DMA channel's hardware semaphore.
- *
- * As used by the MXS platform's DMA software, the DMA channel's hardware
- * semaphore reflects the number of DMA commands the hardware will process, but
- * has not yet finished. This is a volatile value read directly from hardware,
- * so it must be be viewed as immediately stale.
- *
- * If the channel is not marked busy, or has finished processing all its
- * commands, this value should be zero.
- *
- * See mxs_dma_append() for details on how DMA command blocks must be configured
- * to maintain the expected behavior of the semaphore's value.
- */
-static int mxs_dma_read_semaphore(int channel)
-{
- struct apbh_dma *apbh = apbh_dma;
- uint32_t tmp;
- int ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
-
- if (apbh_dma_is_imx23(apbh))
- tmp = readl(apbh->regs + HW_APBHX_CHn_SEMA_MX23(channel));
- else
- tmp = readl(apbh->regs + HW_APBHX_CHn_SEMA_MX28(channel));
-
- tmp &= BM_APBHX_CHn_SEMA_PHORE;
- tmp >>= BP_APBHX_CHn_SEMA_PHORE;
-
- return tmp;
-}
-
-/*
- * Enable a DMA channel.
- *
- * If the given channel has any DMA descriptors on its active list, this
- * function causes the DMA hardware to begin processing them.
- *
- * This function marks the DMA channel as "busy," whether or not there are any
- * descriptors to process.
- */
-static int mxs_dma_enable(int channel)
-{
- struct apbh_dma *apbh = apbh_dma;
- unsigned int sem;
- struct mxs_dma_chan *pchan;
- struct mxs_dma_desc *pdesc;
- int channel_bit, ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
-
- pchan = mxs_dma_channels + channel;
-
- if (pchan->pending_num == 0) {
- pchan->flags |= MXS_DMA_FLAGS_BUSY;
- return 0;
- }
-
- pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
- if (pdesc == NULL)
- return -EFAULT;
-
- if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
- if (!(pdesc->cmd.data & MXS_DMA_DESC_CHAIN))
- return 0;
-
- sem = mxs_dma_read_semaphore(channel);
- if (sem == 0)
- return 0;
-
- if (sem == 1) {
- pdesc = list_entry(pdesc->node.next,
- struct mxs_dma_desc, node);
- if (apbh_dma_is_imx23(apbh))
- writel(mxs_dma_cmd_address(pdesc),
- apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX23(channel));
- else
- writel(mxs_dma_cmd_address(pdesc),
- apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX28(channel));
- }
-
- if (apbh_dma_is_imx23(apbh))
- writel(pchan->pending_num,
- apbh->regs + HW_APBHX_CHn_SEMA_MX23(channel));
- else
- writel(pchan->pending_num,
- apbh->regs + HW_APBHX_CHn_SEMA_MX28(channel));
-
- pchan->active_num += pchan->pending_num;
- pchan->pending_num = 0;
- } else {
- pchan->active_num += pchan->pending_num;
- pchan->pending_num = 0;
- if (apbh_dma_is_imx23(apbh)) {
- writel(mxs_dma_cmd_address(pdesc),
- apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX23(channel));
- writel(pchan->active_num,
- apbh->regs + HW_APBHX_CHn_SEMA_MX23(channel));
- channel_bit = channel + BP_APBH_CTRL0_CLKGATE_CHANNEL;
- } else {
- writel(mxs_dma_cmd_address(pdesc),
- apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX28(channel));
- writel(pchan->active_num,
- apbh->regs + HW_APBHX_CHn_SEMA_MX28(channel));
- channel_bit = channel;
- }
- writel(1 << channel_bit, apbh->regs + HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR);
- }
-
- pchan->flags |= MXS_DMA_FLAGS_BUSY;
- return 0;
-}
-
-/*
- * Disable a DMA channel.
- *
- * This function shuts down a DMA channel and marks it as "not busy." Any
- * descriptors on the active list are immediately moved to the head of the
- * "done" list, whether or not they have actually been processed by the
- * hardware. The "ready" flags of these descriptors are NOT cleared, so they
- * still appear to be active.
- *
- * This function immediately shuts down a DMA channel's hardware, aborting any
- * I/O that may be in progress, potentially leaving I/O hardware in an undefined
- * state. It is unwise to call this function if there is ANY chance the hardware
- * is still processing a command.
- */
-static int mxs_dma_disable(int channel)
-{
- struct mxs_dma_chan *pchan;
- struct apbh_dma *apbh = apbh_dma;
- int channel_bit, ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
-
- pchan = mxs_dma_channels + channel;
-
- if (!(pchan->flags & MXS_DMA_FLAGS_BUSY))
- return -EINVAL;
-
- if (apbh_dma_is_imx23(apbh))
- channel_bit = channel + BP_APBH_CTRL0_CLKGATE_CHANNEL;
- else
- channel_bit = channel + 0;
-
- writel(1 << channel_bit, apbh->regs + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
-
- pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
- pchan->active_num = 0;
- pchan->pending_num = 0;
- list_splice_init(&pchan->active, &pchan->done);
-
return 0;
}
@@ -254,11 +76,6 @@ static int mxs_dma_disable(int channel)
static int mxs_dma_reset(int channel)
{
struct apbh_dma *apbh = apbh_dma;
- int ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
if (apbh_dma_is_imx23(apbh))
writel(1 << (channel + BP_APBH_CTRL0_RESET_CHANNEL),
@@ -270,30 +87,6 @@ static int mxs_dma_reset(int channel)
return 0;
}
-/*
- * Enable or disable DMA interrupt.
- *
- * This function enables the given DMA channel to interrupt the CPU.
- */
-static int mxs_dma_enable_irq(int channel, int enable)
-{
- struct apbh_dma *apbh = apbh_dma;
- int ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
-
- if (enable)
- writel(1 << (channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN),
- apbh->regs + HW_APBHX_CTRL1 + STMP_OFFSET_REG_SET);
- else
- writel(1 << (channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN),
- apbh->regs + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
-
- return 0;
-}
-
/*
* Clear DMA interrupt.
*
@@ -303,11 +96,6 @@ static int mxs_dma_enable_irq(int channel, int enable)
static int mxs_dma_ack_irq(int channel)
{
struct apbh_dma *apbh = apbh_dma;
- int ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
writel(1 << channel, apbh->regs + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
writel(1 << channel, apbh->regs + HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR);
@@ -315,230 +103,12 @@ static int mxs_dma_ack_irq(int channel)
return 0;
}
-/*
- * Request to reserve a DMA channel
- */
-static int mxs_dma_request(int channel)
-{
- struct mxs_dma_chan *pchan;
-
- if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
- return -EINVAL;
-
- pchan = mxs_dma_channels + channel;
- if ((pchan->flags & MXS_DMA_FLAGS_VALID) != MXS_DMA_FLAGS_VALID)
- return -ENODEV;
-
- if (pchan->flags & MXS_DMA_FLAGS_ALLOCATED)
- return -EBUSY;
-
- pchan->flags |= MXS_DMA_FLAGS_ALLOCATED;
- pchan->active_num = 0;
- pchan->pending_num = 0;
-
- INIT_LIST_HEAD(&pchan->active);
- INIT_LIST_HEAD(&pchan->done);
-
- return 0;
-}
-
-/*
- * Release a DMA channel.
- *
- * This function releases a DMA channel from its current owner.
- *
- * The channel will NOT be released if it's marked "busy" (see
- * mxs_dma_enable()).
- */
-static int mxs_dma_release(int channel)
-{
- struct mxs_dma_chan *pchan;
- int ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
-
- pchan = mxs_dma_channels + channel;
-
- if (pchan->flags & MXS_DMA_FLAGS_BUSY)
- return -EBUSY;
-
- pchan->dev = 0;
- pchan->active_num = 0;
- pchan->pending_num = 0;
- pchan->flags &= ~MXS_DMA_FLAGS_ALLOCATED;
-
- return 0;
-}
-
-/*
- * Allocate DMA descriptor
- */
-struct mxs_dma_desc *mxs_dma_desc_alloc(void)
-{
- struct mxs_dma_desc *pdesc;
- dma_addr_t dma_address;
-
- pdesc = dma_alloc_coherent(sizeof(struct mxs_dma_desc),
- &dma_address);
-
- if (pdesc == NULL)
- return NULL;
-
- pdesc->address = dma_address;
-
- return pdesc;
-};
-
-/*
- * Free DMA descriptor
- */
-void mxs_dma_desc_free(struct mxs_dma_desc *pdesc)
-{
- if (pdesc == NULL)
- return;
-
- free(pdesc);
-}
-
-/*
- * Add a DMA descriptor to a channel.
- *
- * If the descriptor list for this channel is not empty, this function sets the
- * CHAIN bit and the NEXTCMD_ADDR fields in the last descriptor's DMA command so
- * it will chain to the new descriptor's command.
- *
- * Then, this function marks the new descriptor as "ready," adds it to the end
- * of the active descriptor list, and increments the count of pending
- * descriptors.
- *
- * The MXS platform DMA software imposes some rules on DMA commands to maintain
- * important invariants. These rules are NOT checked, but they must be carefully
- * applied by software that uses MXS DMA channels.
- *
- * Invariant:
- * The DMA channel's hardware semaphore must reflect the number of DMA
- * commands the hardware will process, but has not yet finished.
- *
- * Explanation:
- * A DMA channel begins processing commands when its hardware semaphore is
- * written with a value greater than zero, and it stops processing commands
- * when the semaphore returns to zero.
- *
- * When a channel finishes a DMA command, it will decrement its semaphore if
- * the DECREMENT_SEMAPHORE bit is set in that command's flags bits.
- *
- * In principle, it's not necessary for the DECREMENT_SEMAPHORE to be set,
- * unless it suits the purposes of the software. For example, one could
- * construct a series of five DMA commands, with the DECREMENT_SEMAPHORE
- * bit set only in the last one. Then, setting the DMA channel's hardware
- * semaphore to one would cause the entire series of five commands to be
- * processed. However, this example would violate the invariant given above.
- *
- * Rule:
- * ALL DMA commands MUST have the DECREMENT_SEMAPHORE bit set so that the DMA
- * channel's hardware semaphore will be decremented EVERY time a command is
- * processed.
- */
-int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc)
-{
- struct mxs_dma_chan *pchan;
- struct mxs_dma_desc *last;
- int ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
-
- pchan = mxs_dma_channels + channel;
-
- pdesc->cmd.next = mxs_dma_cmd_address(pdesc);
- pdesc->flags |= MXS_DMA_DESC_FIRST | MXS_DMA_DESC_LAST;
-
- if (!list_empty(&pchan->active)) {
- last = list_entry(pchan->active.prev, struct mxs_dma_desc,
- node);
-
- pdesc->flags &= ~MXS_DMA_DESC_FIRST;
- last->flags &= ~MXS_DMA_DESC_LAST;
-
- last->cmd.next = mxs_dma_cmd_address(pdesc);
- last->cmd.data |= MXS_DMA_DESC_CHAIN;
- }
- pdesc->flags |= MXS_DMA_DESC_READY;
- if (pdesc->flags & MXS_DMA_DESC_FIRST)
- pchan->pending_num++;
- list_add_tail(&pdesc->node, &pchan->active);
-
- return ret;
-}
-
-/*
- * Clean up processed DMA descriptors.
- *
- * This function removes processed DMA descriptors from the "active" list. Pass
- * in a non-NULL list head to get the descriptors moved to your list. Pass NULL
- * to get the descriptors moved to the channel's "done" list. Descriptors on
- * the "done" list can be retrieved with mxs_dma_get_finished().
- *
- * This function marks the DMA channel as "not busy" if no unprocessed
- * descriptors remain on the "active" list.
- */
-static int mxs_dma_finish(int channel, struct list_head *head)
-{
- int sem;
- struct mxs_dma_chan *pchan;
- struct list_head *p, *q;
- struct mxs_dma_desc *pdesc;
- int ret;
-
- ret = mxs_dma_validate_chan(channel);
- if (ret)
- return ret;
-
- pchan = mxs_dma_channels + channel;
-
- sem = mxs_dma_read_semaphore(channel);
- if (sem < 0)
- return sem;
-
- if (sem == pchan->active_num)
- return 0;
-
- list_for_each_safe(p, q, &pchan->active) {
- if ((pchan->active_num) <= sem)
- break;
-
- pdesc = list_entry(p, struct mxs_dma_desc, node);
- pdesc->flags &= ~MXS_DMA_DESC_READY;
-
- if (head)
- list_move_tail(p, head);
- else
- list_move_tail(p, &pchan->done);
-
- if (pdesc->flags & MXS_DMA_DESC_LAST)
- pchan->active_num--;
- }
-
- if (sem == 0)
- pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
-
- return 0;
-}
-
/*
* Wait for DMA channel to complete
*/
static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
{
struct apbh_dma *apbh = apbh_dma;
- int ret;
-
- ret = mxs_dma_validate_chan(chan);
- if (ret)
- return ret;
while (--timeout) {
if (readl(apbh->regs + HW_APBHX_CTRL1) & (1 << chan))
@@ -546,38 +116,47 @@ static int mxs_dma_wait_complete(uint32_t timeout, unsigned int chan)
udelay(1);
}
- if (timeout == 0) {
- ret = -ETIMEDOUT;
- mxs_dma_reset(chan);
- }
+ if (!timeout)
+ return -ETIMEDOUT;
- return ret;
+ return 0;
}
/*
* Execute the DMA channel
*/
-int mxs_dma_go(int chan)
+int mxs_dma_go(int chan, struct mxs_dma_cmd *cmd, int ncmds)
{
+ struct apbh_dma *apbh = apbh_dma;
uint32_t timeout = 10000;
- int ret;
+ int i, ret, channel_bit;
+
+ ret = mxs_dma_validate_chan(chan);
+ if (ret)
+ return ret;
- LIST_HEAD(tmp_desc_list);
+ for (i = 0; i < ncmds - 1; i++) {
+ cmd[i].next = (unsigned long)(&cmd[i + 1]);
+ cmd[i].data |= MXS_DMA_DESC_CHAIN;
+ }
- mxs_dma_enable_irq(chan, 1);
- mxs_dma_enable(chan);
+ if (apbh_dma_is_imx23(apbh)) {
+ writel(cmd, apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX23(chan));
+ writel(1, apbh->regs + HW_APBHX_CHn_SEMA_MX23(chan));
+ channel_bit = chan + BP_APBH_CTRL0_CLKGATE_CHANNEL;
+ } else {
+ writel(cmd, apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX28(chan));
+ writel(1, apbh->regs + HW_APBHX_CHn_SEMA_MX28(chan));
+ channel_bit = chan;
+ }
+ writel(1 << channel_bit, apbh->regs + HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR);
/* Wait for DMA to finish. */
ret = mxs_dma_wait_complete(timeout, chan);
- /* Clear out the descriptors we just ran. */
- mxs_dma_finish(chan, &tmp_desc_list);
-
/* Shut the DMA channel down. */
mxs_dma_ack_irq(chan);
mxs_dma_reset(chan);
- mxs_dma_enable_irq(chan, 0);
- mxs_dma_disable(chan);
return ret;
}
@@ -589,7 +168,6 @@ static int apbh_dma_probe(struct device_d *dev)
{
struct resource *iores;
struct apbh_dma *apbh;
- struct mxs_dma_chan *pchan;
enum mxs_dma_id id;
int ret, channel;
@@ -627,28 +205,11 @@ static int apbh_dma_probe(struct device_d *dev)
apbh->regs + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
for (channel = 0; channel < MXS_MAX_DMA_CHANNELS; channel++) {
- pchan = mxs_dma_channels + channel;
- pchan->flags = MXS_DMA_FLAGS_VALID;
-
- ret = mxs_dma_request(channel);
-
- if (ret) {
- printf("MXS DMA: Can't acquire DMA channel %i\n",
- channel);
-
- goto err;
- }
-
mxs_dma_reset(channel);
mxs_dma_ack_irq(channel);
}
return 0;
-
-err:
- while (--channel >= 0)
- mxs_dma_release(channel);
- return ret;
}
static struct platform_device_id apbh_ids[] = {
diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index d711708ff2..9f53c437b7 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -102,7 +102,7 @@ struct mxs_nand_info {
loff_t to, struct mtd_oob_ops *ops);
/* DMA descriptors */
- struct mxs_dma_desc **desc;
+ struct mxs_dma_cmd *desc;
uint32_t desc_index;
#define GPMI_ASYNC_EDO_ENABLED (1 << 0)
@@ -118,16 +118,16 @@ static inline int mxs_nand_is_imx6(struct mxs_nand_info *info)
return info->type == GPMI_IMX6;
}
-static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
+static struct mxs_dma_cmd *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
{
- struct mxs_dma_desc *desc;
+ struct mxs_dma_cmd *desc;
if (info->desc_index >= MXS_NAND_DMA_DESCRIPTOR_COUNT) {
printf("MXS NAND: Too many DMA descriptors requested\n");
return NULL;
}
- desc = info->desc[info->desc_index];
+ desc = &info->desc[info->desc_index];
info->desc_index++;
return desc;
@@ -136,12 +136,11 @@ static struct mxs_dma_desc *mxs_nand_get_dma_desc(struct mxs_nand_info *info)
static void mxs_nand_return_dma_descs(struct mxs_nand_info *info)
{
int i;
- struct mxs_dma_desc *desc;
+ struct mxs_dma_cmd *desc;
for (i = 0; i < info->desc_index; i++) {
- desc = info->desc[i];
- memset(desc, 0, sizeof(struct mxs_dma_desc));
- desc->address = (dma_addr_t)desc;
+ desc = &info->desc[i];
+ memset(desc, 0, sizeof(struct mxs_dma_cmd));
}
info->desc_index = 0;
@@ -324,7 +323,7 @@ static int mxs_nand_wait_for_bch_complete(struct mxs_nand_info *nand_info)
static void mxs_nand_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctrl)
{
struct mxs_nand_info *nand_info = chip->priv;
- struct mxs_dma_desc *d;
+ struct mxs_dma_cmd *d;
uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip;
int ret;
@@ -364,15 +363,15 @@ static void mxs_nand_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctr
/* Compile the DMA descriptor -- a descriptor that sends command. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
(nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
- d->cmd.address = (dma_addr_t)nand_info->cmd_buf;
+ d->address = (dma_addr_t)nand_info->cmd_buf;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
@@ -380,10 +379,8 @@ static void mxs_nand_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctr
GPMI_CTRL0_ADDRESS_INCREMENT |
nand_info->cmd_queue_len;
- mxs_dma_desc_append(channel, d);
-
/* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
+ ret = mxs_dma_go(channel, nand_info->desc, nand_info->desc_index);
if (ret)
printf("MXS NAND: Error sending command (%d)\n", ret);
@@ -479,7 +476,7 @@ static void mxs_nand_swap_block_mark(struct nand_chip *chip,
static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
{
struct mxs_nand_info *nand_info = chip->priv;
- struct mxs_dma_desc *d;
+ struct mxs_dma_cmd *d;
uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip;
int ret;
@@ -495,23 +492,21 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
/* Compile the DMA descriptor - a descriptor that reads data. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
(length << MXS_DMA_DESC_BYTES_OFFSET);
- d->cmd.address = (dma_addr_t)nand_info->data_buf;
+ d->address = (dma_addr_t)nand_info->data_buf;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
length;
- mxs_dma_desc_append(channel, d);
-
/*
* A DMA descriptor that waits for the command to end and the chip to
* become ready.
@@ -521,23 +516,21 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
* did that and no one has re-thought it yet.
*/
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
- d->cmd.address = 0;
+ d->address = 0;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
- mxs_dma_desc_append(channel, d);
-
/* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
+ ret = mxs_dma_go(channel, nand_info->desc, nand_info->desc_index);
if (ret) {
printf("MXS NAND: DMA read error\n");
goto rtn;
@@ -556,7 +549,7 @@ static void mxs_nand_write_buf(struct nand_chip *chip, const uint8_t *buf,
int length)
{
struct mxs_nand_info *nand_info = chip->priv;
- struct mxs_dma_desc *d;
+ struct mxs_dma_cmd *d;
uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip;
int ret;
@@ -574,25 +567,23 @@ static void mxs_nand_write_buf(struct nand_chip *chip, const uint8_t *buf,
/* Compile the DMA descriptor - a descriptor that writes data. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
(length << MXS_DMA_DESC_BYTES_OFFSET);
- d->cmd.address = (dma_addr_t)nand_info->data_buf;
+ d->address = (dma_addr_t)nand_info->data_buf;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
length;
- mxs_dma_desc_append(channel, d);
-
/* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
+ ret = mxs_dma_go(channel, nand_info->desc, nand_info->desc_index);
if (ret)
printf("MXS NAND: DMA write error\n");
@@ -644,89 +635,81 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
bool randomizer, int page)
{
struct mxs_nand_info *nand_info = chip->priv;
- struct mxs_dma_desc *d;
+ struct mxs_dma_cmd *d;
int ret;
/* Compile the DMA descriptor - wait for ready. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
- d->cmd.address = 0;
+ d->address = 0;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
- mxs_dma_desc_append(channel, d);
-
/* Compile the DMA descriptor - enable the BCH block and read. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
MXS_DMA_DESC_WAIT4END | (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
- d->cmd.address = 0;
+ d->address = 0;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
readtotal;
- d->cmd.pio_words[1] = 0;
- d->cmd.pio_words[2] =
+ d->pio_words[1] = 0;
+ d->pio_words[2] =
GPMI_ECCCTRL_ENABLE_ECC |
GPMI_ECCCTRL_ECC_CMD_DECODE |
GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
- d->cmd.pio_words[3] = readtotal;
- d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
- d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+ d->pio_words[3] = readtotal;
+ d->pio_words[4] = (dma_addr_t)nand_info->data_buf;
+ d->pio_words[5] = (dma_addr_t)nand_info->oob_buf;
if (randomizer) {
- d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
+ d->pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
GPMI_ECCCTRL_RANDOMIZER_TYPE2;
- d->cmd.pio_words[3] |= (page % 256) << 16;
+ d->pio_words[3] |= (page % 256) << 16;
}
- mxs_dma_desc_append(channel, d);
-
/* Compile the DMA descriptor - disable the BCH block. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
(3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
- d->cmd.address = 0;
+ d->address = 0;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA |
readtotal;
- d->cmd.pio_words[1] = 0;
- d->cmd.pio_words[2] = 0;
-
- mxs_dma_desc_append(channel, d);
+ d->pio_words[1] = 0;
+ d->pio_words[2] = 0;
/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM;
- d->cmd.address = 0;
-
- mxs_dma_desc_append(channel, d);
+ d->address = 0;
/* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
+ ret = mxs_dma_go(channel, nand_info->desc, nand_info->desc_index);
if (ret) {
dev_err(nand_info->dev, "MXS NAND: DMA read error (ecc)\n");
goto out;
@@ -891,7 +874,7 @@ static int mxs_nand_ecc_write_page(struct nand_chip *chip, const uint8_t *buf,
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct mxs_nand_info *nand_info = chip->priv;
- struct mxs_dma_desc *d;
+ struct mxs_dma_cmd *d;
uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip;
int ret = 0;
@@ -905,31 +888,29 @@ static int mxs_nand_ecc_write_page(struct nand_chip *chip, const uint8_t *buf,
/* Compile the DMA descriptor - write data. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data =
+ d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
- d->cmd.address = 0;
+ d->address = 0;
- d->cmd.pio_words[0] =
+ d->pio_words[0] =
GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, nand_info->cur_chip) |
GPMI_CTRL0_ADDRESS_NAND_DATA;
- d->cmd.pio_words[1] = 0;
- d->cmd.pio_words[2] =
+ d->pio_words[1] = 0;
+ d->pio_words[2] =
GPMI_ECCCTRL_ENABLE_ECC |
GPMI_ECCCTRL_ECC_CMD_ENCODE |
GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
- d->cmd.pio_words[3] = (mtd->writesize + mtd->oobsize);
- d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
- d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
-
- mxs_dma_desc_append(channel, d);
+ d->pio_words[3] = (mtd->writesize + mtd->oobsize);
+ d->pio_words[4] = (dma_addr_t)nand_info->data_buf;
+ d->pio_words[5] = (dma_addr_t)nand_info->oob_buf;
/* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
+ ret = mxs_dma_go(channel, nand_info->desc, nand_info->desc_index);
if (ret) {
printf("MXS NAND: DMA write error\n");
goto rtn;
@@ -1242,7 +1223,7 @@ int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size)
struct nand_chip *chip;
struct mtd_info *mtd = mxs_nand_mtd;
struct mxs_nand_info *nand_info;
- struct mxs_dma_desc *d;
+ struct mxs_dma_cmd *d;
uint32_t channel;
int ret = 0;
int page;
@@ -1273,24 +1254,24 @@ int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size)
/* Compile the DMA descriptor - write data. */
d = mxs_nand_get_dma_desc(nand_info);
- d->cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+ d->data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
(6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
- d->cmd.address = 0;
+ d->address = 0;
- d->cmd.pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+ d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
GPMI_CTRL0_ADDRESS_NAND_DATA;
- d->cmd.pio_words[1] = 0;
- d->cmd.pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC |
+ d->pio_words[1] = 0;
+ d->pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC |
GPMI_ECCCTRL_ECC_CMD_ENCODE |
GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
- d->cmd.pio_words[3] = BCH62_PAGESIZE;
- d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
- d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+ d->pio_words[3] = BCH62_PAGESIZE;
+ d->pio_words[4] = (dma_addr_t)nand_info->data_buf;
+ d->pio_words[5] = (dma_addr_t)nand_info->oob_buf;
- d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
+ d->pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
GPMI_ECCCTRL_RANDOMIZER_TYPE2;
/*
* Write NAND page number needed to be randomized
@@ -1299,12 +1280,10 @@ int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size)
* The value is between 0-255. For additional details
* check 9.6.6.4 of i.MX7D Applications Processor reference
*/
- d->cmd.pio_words[3] |= (page % 256) << 16;
-
- mxs_dma_desc_append(channel, d);
+ d->pio_words[3] |= (page % 256) << 16;
/* Execute the DMA chain. */
- ret = mxs_dma_go(channel);
+ ret = mxs_dma_go(channel, nand_info->desc, nand_info->desc_index);
if (ret) {
dev_err(nand_info->dev, "MXS NAND: DMA write error: %d\n", ret);
goto out;
@@ -1416,20 +1395,13 @@ static int mxs_nand_hw_init(struct mxs_nand_info *info)
{
void __iomem *gpmi_regs = info->io_base;
void __iomem *bch_regs = info->bch_base;
- int i = 0, ret;
+ int ret;
u32 val;
- info->desc = malloc(sizeof(struct mxs_dma_desc *) *
- MXS_NAND_DMA_DESCRIPTOR_COUNT);
+ info->desc = dma_alloc_coherent(sizeof(struct mxs_dma_cmd) * MXS_NAND_DMA_DESCRIPTOR_COUNT,
+ DMA_ADDRESS_BROKEN);
if (!info->desc)
- goto err1;
-
- /* Allocate the DMA descriptors. */
- for (i = 0; i < MXS_NAND_DMA_DESCRIPTOR_COUNT; i++) {
- info->desc[i] = mxs_dma_desc_alloc();
- if (!info->desc[i])
- goto err2;
- }
+ return -ENOMEM;
/* Reset the GPMI block. */
ret = stmp_reset_block(gpmi_regs + GPMI_CTRL0, 0);
@@ -1456,14 +1428,6 @@ static int mxs_nand_hw_init(struct mxs_nand_info *info)
writel(val, gpmi_regs + GPMI_CTRL1);
return 0;
-
-err2:
- free(info->desc);
-err1:
- for (--i; i >= 0; i--)
- mxs_dma_desc_free(info->desc[i]);
- printf("MXS NAND: Unable to allocate DMA descriptors\n");
- return -ENOMEM;
}
static void mxs_nand_probe_dt(struct device_d *dev, struct mxs_nand_info *nand_info)
diff --git a/include/dma/apbh-dma.h b/include/dma/apbh-dma.h
index f10bb6f615..e5b5825925 100644
--- a/include/dma/apbh-dma.h
+++ b/include/dma/apbh-dma.h
@@ -88,53 +88,7 @@ struct mxs_dma_cmd {
unsigned long pio_words[APBH_DMA_PIO_WORDS];
};
-/*
- * MXS DMA command descriptor.
- *
- * This structure incorporates an MXS DMA hardware command structure, along
- * with metadata.
- */
-#define MXS_DMA_DESC_FIRST (1 << 0)
-#define MXS_DMA_DESC_LAST (1 << 1)
-#define MXS_DMA_DESC_READY (1 << 31)
-
-struct mxs_dma_desc {
- struct mxs_dma_cmd cmd;
- unsigned int flags;
- dma_addr_t address;
- void *buffer;
- struct list_head node;
-};
-
-/**
- * MXS DMA channel
- *
- * This structure represents a single DMA channel. The MXS platform code
- * maintains an array of these structures to represent every DMA channel in the
- * system (see mxs_dma_channels).
- */
-#define MXS_DMA_FLAGS_IDLE 0
-#define MXS_DMA_FLAGS_BUSY (1 << 0)
-#define MXS_DMA_FLAGS_FREE 0
-#define MXS_DMA_FLAGS_ALLOCATED (1 << 16)
-#define MXS_DMA_FLAGS_VALID (1 << 31)
-
-struct mxs_dma_chan {
- const char *name;
- unsigned long dev;
- struct mxs_dma_device *dma;
- unsigned int flags;
- unsigned int active_num;
- unsigned int pending_num;
- struct list_head active;
- struct list_head done;
-};
-
-struct mxs_dma_desc *mxs_dma_desc_alloc(void);
-void mxs_dma_desc_free(struct mxs_dma_desc *);
-int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc);
-
-int mxs_dma_go(int chan);
+int mxs_dma_go(int chan, struct mxs_dma_cmd *cmd, int ncmds);
int mxs_dma_init(void);
#endif /* __DMA_H__ */
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 05/14] dma: apbh-dma: unify register defines
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (3 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 04/14] dma: apbh-dma: Simplify code Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-01 15:30 ` [PATCH 06/14] ARM: i.MX: xload-gpmi-nand: refactor for more SoC support Sascha Hauer
` (8 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
We have different register defines for the apbh-dma controller. One set
is used in the regular driver, the other one in the xload code. Move the
register defines to a common place and unify their names.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/xload-gpmi-nand.c | 171 ++++++++++------------------
drivers/dma/apbh_dma.c | 27 -----
drivers/mtd/nand/nand_mxs.c | 24 ++--
include/dma/apbh-dma.h | 47 ++++++--
4 files changed, 106 insertions(+), 163 deletions(-)
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index ffbd5c22e3..165c4c5b85 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -14,41 +14,7 @@
#include <soc/imx/gpmi-nand.h>
#include <mach/imx6-regs.h>
#include <mach/clock-imx6.h>
-
-/*
- * MXS DMA hardware command.
- *
- * This structure describes the in-memory layout of an entire DMA command,
- * including space for the maximum number of PIO accesses. See the appropriate
- * reference manual for a detailed description of what these fields mean to the
- * DMA hardware.
- */
-#define DMACMD_COMMAND_DMA_WRITE 0x1
-#define DMACMD_COMMAND_DMA_READ 0x2
-#define DMACMD_COMMAND_DMA_SENSE 0x3
-#define DMACMD_CHAIN (1 << 2)
-#define DMACMD_IRQ (1 << 3)
-#define DMACMD_NAND_LOCK (1 << 4)
-#define DMACMD_NAND_WAIT_4_READY (1 << 5)
-#define DMACMD_DEC_SEM (1 << 6)
-#define DMACMD_WAIT4END (1 << 7)
-#define DMACMD_HALT_ON_TERMINATE (1 << 8)
-#define DMACMD_TERMINATE_FLUSH (1 << 9)
-#define DMACMD_PIO_WORDS(words) ((words) << 12)
-#define DMACMD_XFER_COUNT(x) ((x) << 16)
-
-struct mxs_dma_cmd {
- unsigned long next;
- unsigned long data;
- unsigned long address;
-#define APBH_DMA_PIO_WORDS 6
- unsigned long pio_words[APBH_DMA_PIO_WORDS];
-};
-
-enum mxs_dma_id {
- IMX23_DMA,
- IMX28_DMA,
-};
+#include <dma/apbh-dma.h>
struct apbh_dma {
void __iomem *regs;
@@ -61,25 +27,6 @@ struct mxs_dma_chan {
struct apbh_dma *apbh;
};
-#define HW_APBHX_CTRL0 0x000
-#define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29)
-#define BM_APBH_CTRL0_APB_BURST_EN (1 << 28)
-#define BP_APBH_CTRL0_CLKGATE_CHANNEL 8
-#define BP_APBH_CTRL0_RESET_CHANNEL 16
-#define HW_APBHX_CTRL1 0x010
-#define BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN 16
-#define HW_APBHX_CTRL2 0x020
-#define HW_APBHX_CHANNEL_CTRL 0x030
-#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16
-#define BP_APBHX_VERSION_MAJOR 24
-#define HW_APBHX_CHn_NXTCMDAR_MX23(n) (0x050 + (n) * 0x70)
-#define HW_APBHX_CHn_NXTCMDAR_MX28(n) (0x110 + (n) * 0x70)
-#define HW_APBHX_CHn_SEMA_MX23(n) (0x080 + (n) * 0x70)
-#define HW_APBHX_CHn_SEMA_MX28(n) (0x140 + (n) * 0x70)
-#define NAND_ONFI_CRC_BASE 0x4f4e
-
-#define apbh_dma_is_imx23(aphb) ((apbh)->id == IMX23_DMA)
-
/* udelay() is not available in PBL, need to improvise */
static void __udelay(int us)
{
@@ -168,7 +115,7 @@ static int mxs_dma_run(struct mxs_dma_chan *pchan, struct mxs_dma_cmd *pdesc,
/* chain descriptors */
for (i = 0; i < num - 1; i++) {
pdesc[i].next = (unsigned long)(&pdesc[i + 1]);
- pdesc[i].data |= DMACMD_CHAIN;
+ pdesc[i].data |= MXS_DMA_DESC_CHAIN;
}
writel(1 << (pchan->channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN),
@@ -313,10 +260,10 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
if ((max_pagenum - 1) >= SZ_64K)
cmd_buf[cmd_queue_len++] = pagenum >> 16;
- d->data = DMACMD_COMMAND_DMA_READ |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(cmd_queue_len);
+ d->data = MXS_DMA_DESC_COMMAND_DMA_READ |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(cmd_queue_len);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
@@ -333,10 +280,10 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
cmd_buf[cmd_queue_len++] = NAND_CMD_READSTART;
- d->data = DMACMD_COMMAND_DMA_READ |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(cmd_queue_len);
+ d->data = MXS_DMA_DESC_COMMAND_DMA_READ |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(cmd_queue_len);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
@@ -347,10 +294,10 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
/* Compile DMA descriptor - wait for ready. */
d = &info->desc[descnum++];
- d->data = DMACMD_CHAIN |
- DMACMD_NAND_WAIT_4_READY |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(2);
+ d->data = MXS_DMA_DESC_CHAIN |
+ MXS_DMA_DESC_NAND_WAIT_4_READY |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(2);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
@@ -360,10 +307,10 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
if (raw) {
/* Compile DMA descriptor - read. */
d = &info->desc[descnum++];
- d->data = DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(writesize + oobsize) |
- DMACMD_COMMAND_DMA_WRITE;
+ d->data = MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(writesize + oobsize) |
+ MXS_DMA_DESC_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
@@ -373,7 +320,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
} else {
/* Compile DMA descriptor - enable the BCH block and read. */
d = &info->desc[descnum++];
- d->data = DMACMD_WAIT4END | DMACMD_PIO_WORDS(6);
+ d->data = MXS_DMA_DESC_WAIT4END | MXS_DMA_DESC_PIO_WORDS(6);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
@@ -389,9 +336,9 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
/* Compile DMA descriptor - disable the BCH block. */
d = &info->desc[descnum++];
- d->data = DMACMD_NAND_WAIT_4_READY |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(3);
+ d->data = MXS_DMA_DESC_NAND_WAIT_4_READY |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(3);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
@@ -401,7 +348,7 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
d = &info->desc[descnum++];
- d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+ d->data = MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
/* Execute the DMA chain. */
ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
@@ -460,10 +407,10 @@ static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
d->address = (dma_addr_t)(cmd_buf);
cmd_buf[cmd_queue_len++] = NAND_CMD_STATUS;
- d->data = DMACMD_COMMAND_DMA_READ |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(cmd_queue_len);
+ d->data = MXS_DMA_DESC_COMMAND_DMA_READ |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(cmd_queue_len);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
@@ -474,10 +421,10 @@ static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
/* Compile DMA descriptor - read. */
d = &info->desc[descnum++];
- d->data = DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(1) |
- DMACMD_COMMAND_DMA_WRITE;
+ d->data = MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(1) |
+ MXS_DMA_DESC_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
@@ -487,7 +434,7 @@ static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
d = &info->desc[descnum++];
- d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+ d->data = MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
/* Execute the DMA chain. */
ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
@@ -518,10 +465,10 @@ static int mxs_nand_reset(struct mxs_nand_info *info, void *databuf)
d->address = (dma_addr_t)(cmd_buf);
cmd_buf[cmd_queue_len++] = NAND_CMD_RESET;
- d->data = DMACMD_COMMAND_DMA_READ |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(cmd_queue_len);
+ d->data = MXS_DMA_DESC_COMMAND_DMA_READ |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(cmd_queue_len);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
@@ -532,7 +479,7 @@ static int mxs_nand_reset(struct mxs_nand_info *info, void *databuf)
/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
d = &info->desc[descnum++];
- d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+ d->data = MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
/* Execute the DMA chain. */
ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
@@ -590,10 +537,10 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
cmd_buf[cmd_queue_len++] = NAND_CMD_PARAM;
cmd_buf[cmd_queue_len++] = 0x00;
- d->data = DMACMD_COMMAND_DMA_READ |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(cmd_queue_len);
+ d->data = MXS_DMA_DESC_COMMAND_DMA_READ |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(cmd_queue_len);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
@@ -604,10 +551,10 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
/* Compile DMA descriptor - wait for ready. */
d = &info->desc[descnum++];
- d->data = DMACMD_CHAIN |
- DMACMD_NAND_WAIT_4_READY |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(2);
+ d->data = MXS_DMA_DESC_CHAIN |
+ MXS_DMA_DESC_NAND_WAIT_4_READY |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(2);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
GPMI_CTRL0_WORD_LENGTH |
@@ -616,10 +563,10 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
/* Compile DMA descriptor - read. */
d = &info->desc[descnum++];
- d->data = DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(sizeof(struct nand_onfi_params)) |
- DMACMD_COMMAND_DMA_WRITE;
+ d->data = MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(sizeof(struct nand_onfi_params)) |
+ MXS_DMA_DESC_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
@@ -629,7 +576,7 @@ static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
d = &info->desc[descnum++];
- d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+ d->data = MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
/* Execute the DMA chain. */
ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
@@ -687,10 +634,10 @@ static int mxs_nand_read_id(struct mxs_nand_info *info, u8 adr, void *databuf, s
cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
cmd_buf[cmd_queue_len++] = adr;
- d->data = DMACMD_COMMAND_DMA_READ |
- DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(cmd_queue_len);
+ d->data = MXS_DMA_DESC_COMMAND_DMA_READ |
+ MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(cmd_queue_len);
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
GPMI_CTRL0_WORD_LENGTH |
@@ -701,10 +648,10 @@ static int mxs_nand_read_id(struct mxs_nand_info *info, u8 adr, void *databuf, s
/* Compile DMA descriptor - read. */
d = &info->desc[descnum++];
- d->data = DMACMD_WAIT4END |
- DMACMD_PIO_WORDS(1) |
- DMACMD_XFER_COUNT(len) |
- DMACMD_COMMAND_DMA_WRITE;
+ d->data = MXS_DMA_DESC_WAIT4END |
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(len) |
+ MXS_DMA_DESC_COMMAND_DMA_WRITE;
d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
GPMI_CTRL0_WORD_LENGTH |
FIELD_PREP(GPMI_CTRL0_CS, info->cs) |
@@ -714,7 +661,7 @@ static int mxs_nand_read_id(struct mxs_nand_info *info, u8 adr, void *databuf, s
/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
d = &info->desc[descnum++];
- d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+ d->data = MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
/* Execute the DMA chain. */
ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c
index e93bffd595..767c095314 100644
--- a/drivers/dma/apbh_dma.c
+++ b/drivers/dma/apbh_dma.c
@@ -24,39 +24,12 @@
#include <init.h>
#include <io.h>
-
-#define HW_APBHX_CTRL0 0x000
-#define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29)
-#define BM_APBH_CTRL0_APB_BURST_EN (1 << 28)
-#define BP_APBH_CTRL0_CLKGATE_CHANNEL 8
-#define BP_APBH_CTRL0_RESET_CHANNEL 16
-#define HW_APBHX_CTRL1 0x010
-#define BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN 16
-#define HW_APBHX_CTRL2 0x020
-#define HW_APBHX_CHANNEL_CTRL 0x030
-#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16
-#define BP_APBHX_VERSION_MAJOR 24
-#define HW_APBHX_CHn_NXTCMDAR_MX23(n) (0x050 + (n) * 0x70)
-#define HW_APBHX_CHn_NXTCMDAR_MX28(n) (0x110 + (n) * 0x70)
-#define HW_APBHX_CHn_SEMA_MX23(n) (0x080 + (n) * 0x70)
-#define HW_APBHX_CHn_SEMA_MX28(n) (0x140 + (n) * 0x70)
-#define BM_APBHX_CHn_SEMA_PHORE (0xff << 16)
-#define BP_APBHX_CHn_SEMA_PHORE 16
-
-enum mxs_dma_id {
- UNKNOWN_DMA_ID,
- IMX23_DMA,
- IMX28_DMA,
-};
-
struct apbh_dma {
void __iomem *regs;
struct clk *clk;
enum mxs_dma_id id;
};
-#define apbh_dma_is_imx23(aphb) ((apbh)->id == IMX23_DMA)
-
static struct apbh_dma *apbh_dma;
/*
diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index 9f53c437b7..b162c23743 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -366,8 +366,8 @@ static void mxs_nand_cmd_ctrl(struct nand_chip *chip, int data, unsigned int ctr
d->data =
MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_CHAIN | MXS_DMA_DESC_DEC_SEM |
- MXS_DMA_DESC_WAIT4END | (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
- (nand_info->cmd_queue_len << MXS_DMA_DESC_BYTES_OFFSET);
+ MXS_DMA_DESC_WAIT4END | MXS_DMA_DESC_PIO_WORDS(3) |
+ MXS_DMA_DESC_XFER_COUNT(nand_info->cmd_queue_len);
d->address = (dma_addr_t)nand_info->cmd_buf;
@@ -495,8 +495,8 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
d->data =
MXS_DMA_DESC_COMMAND_DMA_WRITE | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
- (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
- (length << MXS_DMA_DESC_BYTES_OFFSET);
+ MXS_DMA_DESC_PIO_WORDS(1) |
+ MXS_DMA_DESC_XFER_COUNT(length);
d->address = (dma_addr_t)nand_info->data_buf;
@@ -519,7 +519,7 @@ static void mxs_nand_read_buf(struct nand_chip *chip, uint8_t *buf, int length)
d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_DEC_SEM |
- MXS_DMA_DESC_WAIT4END | (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+ MXS_DMA_DESC_WAIT4END | MXS_DMA_DESC_PIO_WORDS(4);
d->address = 0;
@@ -570,8 +570,8 @@ static void mxs_nand_write_buf(struct nand_chip *chip, const uint8_t *buf,
d->data =
MXS_DMA_DESC_COMMAND_DMA_READ | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
- (4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
- (length << MXS_DMA_DESC_BYTES_OFFSET);
+ MXS_DMA_DESC_PIO_WORDS(4) |
+ MXS_DMA_DESC_XFER_COUNT(length);
d->address = (dma_addr_t)nand_info->data_buf;
@@ -643,7 +643,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
- (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+ MXS_DMA_DESC_PIO_WORDS(1);
d->address = 0;
@@ -657,7 +657,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
d = mxs_nand_get_dma_desc(nand_info);
d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
- MXS_DMA_DESC_WAIT4END | (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+ MXS_DMA_DESC_WAIT4END | MXS_DMA_DESC_PIO_WORDS(6);
d->address = 0;
@@ -687,7 +687,7 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
MXS_DMA_DESC_NAND_WAIT_4_READY | MXS_DMA_DESC_WAIT4END |
- (3 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+ MXS_DMA_DESC_PIO_WORDS(3);
d->address = 0;
@@ -891,7 +891,7 @@ static int mxs_nand_ecc_write_page(struct nand_chip *chip, const uint8_t *buf,
d->data =
MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
- (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+ MXS_DMA_DESC_PIO_WORDS(6);
d->address = 0;
@@ -1256,7 +1256,7 @@ int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size)
d = mxs_nand_get_dma_desc(nand_info);
d->data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
- (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+ MXS_DMA_DESC_PIO_WORDS(6);
d->address = 0;
diff --git a/include/dma/apbh-dma.h b/include/dma/apbh-dma.h
index e5b5825925..4584b504c2 100644
--- a/include/dma/apbh-dma.h
+++ b/include/dma/apbh-dma.h
@@ -30,6 +30,31 @@
#define MXS_DMA_ALIGNMENT 32
+#define HW_APBHX_CTRL0 0x000
+#define BM_APBH_CTRL0_APB_BURST8_EN BIT(29)
+#define BM_APBH_CTRL0_APB_BURST_EN BIT(28)
+#define BP_APBH_CTRL0_CLKGATE_CHANNEL 8
+#define BP_APBH_CTRL0_RESET_CHANNEL 16
+#define HW_APBHX_CTRL1 0x010
+#define BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN 16
+#define HW_APBHX_CTRL2 0x020
+#define HW_APBHX_CHANNEL_CTRL 0x030
+#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16
+#define BP_APBHX_VERSION_MAJOR 24
+#define HW_APBHX_CHn_NXTCMDAR_MX23(n) (0x050 + (n) * 0x70)
+#define HW_APBHX_CHn_NXTCMDAR_MX28(n) (0x110 + (n) * 0x70)
+#define HW_APBHX_CHn_SEMA_MX23(n) (0x080 + (n) * 0x70)
+#define HW_APBHX_CHn_SEMA_MX28(n) (0x140 + (n) * 0x70)
+#define NAND_ONFI_CRC_BASE 0x4f4e
+
+enum mxs_dma_id {
+ UNKNOWN_DMA_ID,
+ IMX23_DMA,
+ IMX28_DMA,
+};
+
+#define apbh_dma_is_imx23(aphb) ((apbh)->id == IMX23_DMA)
+
/*
* MXS DMA channels
*/
@@ -64,18 +89,16 @@ enum {
#define MXS_DMA_DESC_COMMAND_DMA_WRITE 0x1
#define MXS_DMA_DESC_COMMAND_DMA_READ 0x2
#define MXS_DMA_DESC_COMMAND_DMA_SENSE 0x3
-#define MXS_DMA_DESC_CHAIN (1 << 2)
-#define MXS_DMA_DESC_IRQ (1 << 3)
-#define MXS_DMA_DESC_NAND_LOCK (1 << 4)
-#define MXS_DMA_DESC_NAND_WAIT_4_READY (1 << 5)
-#define MXS_DMA_DESC_DEC_SEM (1 << 6)
-#define MXS_DMA_DESC_WAIT4END (1 << 7)
-#define MXS_DMA_DESC_HALT_ON_TERMINATE (1 << 8)
-#define MXS_DMA_DESC_TERMINATE_FLUSH (1 << 9)
-#define MXS_DMA_DESC_PIO_WORDS_MASK (0xf << 12)
-#define MXS_DMA_DESC_PIO_WORDS_OFFSET 12
-#define MXS_DMA_DESC_BYTES_MASK (0xffff << 16)
-#define MXS_DMA_DESC_BYTES_OFFSET 16
+#define MXS_DMA_DESC_CHAIN BIT(2)
+#define MXS_DMA_DESC_IRQ BIT(3)
+#define MXS_DMA_DESC_NAND_LOCK BIT(4)
+#define MXS_DMA_DESC_NAND_WAIT_4_READY BIT(5)
+#define MXS_DMA_DESC_DEC_SEM BIT(6)
+#define MXS_DMA_DESC_WAIT4END BIT(7)
+#define MXS_DMA_DESC_HALT_ON_TERMINATE BIT(8)
+#define MXS_DMA_DESC_TERMINATE_FLUSH BIT(9)
+#define MXS_DMA_DESC_PIO_WORDS(words) ((words) << 12)
+#define MXS_DMA_DESC_XFER_COUNT(x) ((x) << 16)
struct mxs_dma_cmd {
unsigned long next;
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 06/14] ARM: i.MX: xload-gpmi-nand: refactor for more SoC support
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (4 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 05/14] dma: apbh-dma: unify register defines Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-01 15:30 ` [PATCH 07/14] imx-bbu-nand-fcb: pull printing debug info out of get_fcb() Sascha Hauer
` (7 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List; +Cc: Ahmad Fatoum
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
The code hardcodes i.MX6 addresses, which needs to be factored out for
use in other SoCs' startup. Do this by creating a new imx_nand_params
to hold these information and passing it into the now more generic
code.
No functional change intended. Untested as I got no i.MX6 directly
booting from NAND.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/mach-imx/include/mach/imx6-regs.h | 2 +
arch/arm/mach-imx/xload-gpmi-nand.c | 76 ++++++++++++----------
2 files changed, 44 insertions(+), 34 deletions(-)
diff --git a/arch/arm/mach-imx/include/mach/imx6-regs.h b/arch/arm/mach-imx/include/mach/imx6-regs.h
index 35f03036cb..39e2751533 100644
--- a/arch/arm/mach-imx/include/mach/imx6-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx6-regs.h
@@ -3,7 +3,9 @@
#ifndef __MACH_IMX6_REGS_H
#define __MACH_IMX6_REGS_H
+#define MX6_APBH_BASE_ADDR 0x00110000
#define MX6_GPMI_BASE_ADDR 0x00112000
+#define MX6_BCH_BASE_ADDR 0x00114000
#define MX6_FAST1_BASE_ADDR 0x00c00000
#define MX6_FAST2_BASE_ADDR 0x00b00000
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 165c4c5b85..a7398cc26a 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -999,49 +999,44 @@ static int read_firmware(struct mxs_nand_info *info, int startpage,
return 0;
}
-static int __maybe_unused imx6_nand_load_image(void *cmdbuf, void *descs,
- void *databuf, void *dest, int len)
+struct imx_nand_params {
+ struct mxs_nand_info info;
+ struct apbh_dma apbh;
+ void *sdram;
+};
+
+static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
+ void *databuf, void *dest, int len)
{
- struct mxs_nand_info info = {
- .io_base = (void *)0x00112000,
- .bch_base = (void *)0x00114000,
- };
- struct apbh_dma apbh = {
- .id = IMX28_DMA,
- .regs = (void *)0x00110000,
- };
+ struct mxs_nand_info *info = ¶ms->info;
struct mxs_dma_chan pchan = {
.channel = 0, /* MXS: MXS_DMA_CHANNEL_AHB_APBH_GPMI0 */
- .apbh = &apbh,
+ .apbh = ¶ms->apbh,
};
int ret;
struct fcb_block *fcb;
- info.dma_channel = &pchan;
+ info->dma_channel = &pchan;
pr_debug("cmdbuf: 0x%p descs: 0x%p databuf: 0x%p dest: 0x%p\n",
- cmdbuf, descs, databuf, dest);
-
- /* Command buffers */
- info.cmd_buf = cmdbuf;
- info.desc = descs;
+ info->cmd_buf, info->desc, databuf, dest);
- ret = mxs_nand_get_info(&info, databuf);
+ ret = mxs_nand_get_info(info, databuf);
if (ret)
return ret;
- ret = get_fcb(&info, databuf);
+ ret = get_fcb(info, databuf);
if (ret)
return ret;
- fcb = &info.fcb;
+ fcb = &info->fcb;
- get_dbbt(&info, databuf);
+ get_dbbt(info, databuf);
- ret = read_firmware(&info, fcb->Firmware1_startingPage, dest, len);
+ ret = read_firmware(info, fcb->Firmware1_startingPage, dest, len);
if (ret) {
pr_err("Failed to read firmware1, trying firmware2\n");
- ret = read_firmware(&info, fcb->Firmware2_startingPage,
+ ret = read_firmware(info, fcb->Firmware2_startingPage,
dest, len);
if (ret) {
pr_err("Failed to also read firmware2\n");
@@ -1052,24 +1047,21 @@ static int __maybe_unused imx6_nand_load_image(void *cmdbuf, void *descs,
return 0;
}
-int imx6_nand_start_image(void)
+static int imx_nand_start_image(struct imx_nand_params *params)
{
+ struct mxs_nand_info *info = ¶ms->info;
int ret;
- void *sdram = (void *)0x10000000;
void __noreturn (*bb)(void);
- void *cmdbuf, *databuf, *descs;
+ void *databuf;
- cmdbuf = sdram;
- descs = sdram + MXS_NAND_COMMAND_BUFFER_SIZE;
- databuf = descs +
+ /* Command buffers */
+ info->cmd_buf = params->sdram;
+ info->desc = params->sdram + MXS_NAND_COMMAND_BUFFER_SIZE;
+ databuf = info->desc +
sizeof(struct mxs_dma_cmd) * MXS_NAND_DMA_DESCRIPTOR_COUNT;
bb = (void *)PAGE_ALIGN((unsigned long)databuf + SZ_8K);
- /* Apply ERR007117 workaround */
- imx6_errata_007117_enable();
-
- ret = imx6_nand_load_image(cmdbuf, descs, databuf,
- bb, imx_image_size());
+ ret = imx6_nand_load_image(params, databuf, bb, imx_image_size());
if (ret) {
pr_err("Loading image failed: %d\n", ret);
return ret;
@@ -1082,3 +1074,19 @@ int imx6_nand_start_image(void)
bb();
}
+
+int imx6_nand_start_image(void)
+{
+ static struct imx_nand_params params = {
+ .info.io_base = IOMEM(MX6_GPMI_BASE_ADDR),
+ .info.bch_base = IOMEM(MX6_BCH_BASE_ADDR),
+ .apbh.regs = IOMEM(MX6_APBH_BASE_ADDR),
+ .apbh.id = IMX28_DMA,
+ .sdram = (void *)MX6_MMDC_PORT01_BASE_ADDR,
+ };
+
+ /* Apply ERR007117 workaround */
+ imx6_errata_007117_enable();
+
+ return imx_nand_start_image(¶ms);
+}
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 07/14] imx-bbu-nand-fcb: pull printing debug info out of get_fcb()
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (5 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 06/14] ARM: i.MX: xload-gpmi-nand: refactor for more SoC support Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-01 15:30 ` [PATCH 08/14] ARM: i.MX: xload nand: Pull ECC status checking out of read page Sascha Hauer
` (6 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
get_fcb() will be split into SoC specific variants. As a preparation
pull printing the fcb debug info out of this function to not have
to duplicate it in the SoC specific variants later.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/xload-gpmi-nand.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index a7398cc26a..dc4cc45be0 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -869,17 +869,6 @@ static int get_fcb(struct mxs_nand_info *info, void *databuf)
continue;
}
- pr_debug("Found FCB:\n");
- pr_debug("PageDataSize: 0x%08x\n", fcb->PageDataSize);
- pr_debug("TotalPageSize: 0x%08x\n", fcb->TotalPageSize);
- pr_debug("SectorsPerBlock: 0x%08x\n", fcb->SectorsPerBlock);
- pr_debug("FW1_startingPage: 0x%08x\n",
- fcb->Firmware1_startingPage);
- pr_debug("PagesInFW1: 0x%08x\n", fcb->PagesInFirmware1);
- pr_debug("FW2_startingPage: 0x%08x\n",
- fcb->Firmware2_startingPage);
- pr_debug("PagesInFW2: 0x%08x\n", fcb->PagesInFirmware2);
-
return 0;
}
@@ -1031,6 +1020,17 @@ static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
fcb = &info->fcb;
+ pr_debug("Found FCB:\n");
+ pr_debug("PageDataSize: 0x%08x\n", fcb->PageDataSize);
+ pr_debug("TotalPageSize: 0x%08x\n", fcb->TotalPageSize);
+ pr_debug("SectorsPerBlock: 0x%08x\n", fcb->SectorsPerBlock);
+ pr_debug("FW1_startingPage: 0x%08x\n",
+ fcb->Firmware1_startingPage);
+ pr_debug("PagesInFW1: 0x%08x\n", fcb->PagesInFirmware1);
+ pr_debug("FW2_startingPage: 0x%08x\n",
+ fcb->Firmware2_startingPage);
+ pr_debug("PagesInFW2: 0x%08x\n", fcb->PagesInFirmware2);
+
get_dbbt(info, databuf);
ret = read_firmware(info, fcb->Firmware1_startingPage, dest, len);
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 08/14] ARM: i.MX: xload nand: Pull ECC status checking out of read page
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (6 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 07/14] imx-bbu-nand-fcb: pull printing debug info out of get_fcb() Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-02 8:33 ` Marco Felsch
2022-11-01 15:30 ` [PATCH 09/14] ARM: i.MX: xload nand: Use final page layout from FCB Sascha Hauer
` (5 subsequent siblings)
13 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
The read page code can be reused by upcoming i.MX7 support, but the ECC
checking will be different. Pull ECC status checking out of the read
page code to make that reusable on i.MX7.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/xload-gpmi-nand.c | 42 ++++++++++++++++++++---------
1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index dc4cc45be0..543ec108ba 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -236,8 +236,6 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
int cmd_queue_len;
u8 *cmd_buf;
int ret;
- uint8_t *status;
- int i;
int timeout;
int descnum = 0;
int max_pagenum = info->nand_size /
@@ -375,20 +373,26 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
writel(BCH_CTRL_COMPLETE_IRQ,
bch_regs + BCH_CTRL + STMP_OFFSET_REG_CLR);
- /* Loop over status bytes, accumulating ECC status. */
- status = databuf + writesize + mxs_nand_aux_status_offset();
- for (i = 0; i < writesize / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; i++) {
- if (status[i] == 0xfe) {
- ret = -EBADMSG;
- goto err;
- }
- }
-
ret = 0;
err:
return ret;
}
+static int mxs_nand_get_ecc_status(struct mxs_nand_info *info, void *databuf)
+{
+ uint8_t *status;
+ int i;
+
+ /* Loop over status bytes, accumulating ECC status. */
+ status = databuf + info->organization.pagesize + mxs_nand_aux_status_offset();
+ for (i = 0; i < info->organization.pagesize / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; i++) {
+ if (status[i] == 0xfe)
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
{
int ret;
@@ -851,6 +855,10 @@ static int get_fcb(struct mxs_nand_info *info, void *databuf)
if (ret)
continue;
+ ret = mxs_nand_get_ecc_status(info, databuf);
+ if (ret)
+ continue;
+
memcpy(fcb, databuf + mxs_nand_aux_status_offset(),
sizeof(*fcb));
@@ -886,7 +894,11 @@ static int get_dbbt(struct mxs_nand_info *info, void *databuf)
page = startpage + i * info->organization.pages_per_eraseblock;
ret = mxs_nand_read_page(info, info->organization.pagesize,
- info->organization.oobsize, page, databuf, 0);
+ info->organization.oobsize, page, databuf, 0, false);
+ if (ret)
+ continue;
+
+ ret = mxs_nand_get_ecc_status(info, databuf);
if (ret)
continue;
@@ -900,7 +912,11 @@ static int get_dbbt(struct mxs_nand_info *info, void *databuf)
return -ENOENT;
ret = mxs_nand_read_page(info, info->organization.pagesize,
- info->organization.oobsize, page + 4, databuf, 0);
+ info->organization.oobsize, page + 4, databuf, 0, false);
+ if (ret)
+ continue;
+
+ ret = mxs_nand_get_ecc_status(info, databuf);
if (ret)
continue;
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 08/14] ARM: i.MX: xload nand: Pull ECC status checking out of read page
2022-11-01 15:30 ` [PATCH 08/14] ARM: i.MX: xload nand: Pull ECC status checking out of read page Sascha Hauer
@ 2022-11-02 8:33 ` Marco Felsch
0 siblings, 0 replies; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 8:33 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
Hi Sascha,
On 22-11-01, Sascha Hauer wrote:
> The read page code can be reused by upcoming i.MX7 support, but the ECC
> checking will be different. Pull ECC status checking out of the read
> page code to make that reusable on i.MX7.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/mach-imx/xload-gpmi-nand.c | 42 ++++++++++++++++++++---------
> 1 file changed, 29 insertions(+), 13 deletions(-)
>
> diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
> index dc4cc45be0..543ec108ba 100644
> --- a/arch/arm/mach-imx/xload-gpmi-nand.c
> +++ b/arch/arm/mach-imx/xload-gpmi-nand.c
> @@ -236,8 +236,6 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> int cmd_queue_len;
> u8 *cmd_buf;
> int ret;
> - uint8_t *status;
> - int i;
> int timeout;
> int descnum = 0;
> int max_pagenum = info->nand_size /
> @@ -375,20 +373,26 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> writel(BCH_CTRL_COMPLETE_IRQ,
> bch_regs + BCH_CTRL + STMP_OFFSET_REG_CLR);
>
> - /* Loop over status bytes, accumulating ECC status. */
> - status = databuf + writesize + mxs_nand_aux_status_offset();
> - for (i = 0; i < writesize / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; i++) {
> - if (status[i] == 0xfe) {
> - ret = -EBADMSG;
> - goto err;
> - }
> - }
> -
> ret = 0;
> err:
> return ret;
> }
>
> +static int mxs_nand_get_ecc_status(struct mxs_nand_info *info, void *databuf)
> +{
> + uint8_t *status;
> + int i;
> +
> + /* Loop over status bytes, accumulating ECC status. */
> + status = databuf + info->organization.pagesize + mxs_nand_aux_status_offset();
> + for (i = 0; i < info->organization.pagesize / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; i++) {
> + if (status[i] == 0xfe)
> + return -EBADMSG;
> + }
> +
> + return 0;
> +}
> +
> static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
> {
> int ret;
> @@ -851,6 +855,10 @@ static int get_fcb(struct mxs_nand_info *info, void *databuf)
> if (ret)
> continue;
>
> + ret = mxs_nand_get_ecc_status(info, databuf);
> + if (ret)
> + continue;
> +
> memcpy(fcb, databuf + mxs_nand_aux_status_offset(),
> sizeof(*fcb));
>
> @@ -886,7 +894,11 @@ static int get_dbbt(struct mxs_nand_info *info, void *databuf)
> page = startpage + i * info->organization.pages_per_eraseblock;
>
> ret = mxs_nand_read_page(info, info->organization.pagesize,
> - info->organization.oobsize, page, databuf, 0);
> + info->organization.oobsize, page, databuf, 0, false);
Maybe I didn't saw the change, but where did you changed the function
declaration?
Regards,
Marco
> + if (ret)
> + continue;
> +
> + ret = mxs_nand_get_ecc_status(info, databuf);
> if (ret)
> continue;
>
> @@ -900,7 +912,11 @@ static int get_dbbt(struct mxs_nand_info *info, void *databuf)
> return -ENOENT;
>
> ret = mxs_nand_read_page(info, info->organization.pagesize,
> - info->organization.oobsize, page + 4, databuf, 0);
> + info->organization.oobsize, page + 4, databuf, 0, false);
> + if (ret)
> + continue;
> +
> + ret = mxs_nand_get_ecc_status(info, databuf);
> if (ret)
> continue;
>
> --
> 2.30.2
>
>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 09/14] ARM: i.MX: xload nand: Use final page layout from FCB
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (7 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 08/14] ARM: i.MX: xload nand: Pull ECC status checking out of read page Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-01 15:30 ` [PATCH 10/14] imx-bbu-nand-fcb: Fix reading FCB information from BCH registers Sascha Hauer
` (4 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
For non ONFI NAND chips we decode the page layout from the extended ID
information from NAND (basically what nand_decode_ext_id() does in the
MTD layer). For some chips this information is not entirely correct
though. For example some Toshiba chips have this quirk:
/*
* Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
* 512B page. For Toshiba SLC, we decode the 5th/6th byte as
* follows:
* - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
* 110b -> 24nm
* - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC
*/
if (chip->id.len >= 6 && nand_is_slc(chip) &&
(chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
!(chip->id.data[4] & TOSHIBA_NAND_ID4_IS_BENAND) /* !BENAND */) {
memorg->oobsize = 32 * memorg->pagesize >> 9;
mtd->oobsize = memorg->oobsize;
}
We could try and add these kind of quirks into the xload code, but we
already have the correct information in the FCB. So as long as the
initial information from the ID is enough to read the FCB, we can use
the information containekd therein for further reading from the NAND.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/xload-gpmi-nand.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 543ec108ba..af20c11fa6 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -1020,6 +1020,8 @@ static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
};
int ret;
struct fcb_block *fcb;
+ void __iomem *bch_regs = info->bch_base;
+ u32 fl0, fl1;
info->dma_channel = &pchan;
@@ -1047,6 +1049,21 @@ static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
fcb->Firmware2_startingPage);
pr_debug("PagesInFW2: 0x%08x\n", fcb->PagesInFirmware2);
+ info->organization.oobsize = fcb->TotalPageSize - fcb->PageDataSize;
+ info->organization.pagesize = fcb->PageDataSize;
+
+ fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, fcb->NumEccBlocksPerPage) |
+ FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, fcb->MetadataBytes) |
+ FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, fcb->EccBlock0EccType) |
+ (fcb->BCHType ? BCH_FLASHLAYOUT0_GF13_0_GF14_1 : 0) |
+ FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, fcb->EccBlock0Size / 4);
+ fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, fcb->TotalPageSize) |
+ FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, fcb->EccBlockNEccType) |
+ (fcb->BCHType ? BCH_FLASHLAYOUT1_GF13_0_GF14_1 : 0) |
+ FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, fcb->EccBlockNSize / 4);
+ writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
+ writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
+
get_dbbt(info, databuf);
ret = read_firmware(info, fcb->Firmware1_startingPage, dest, len);
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 10/14] imx-bbu-nand-fcb: Fix reading FCB information from BCH registers
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (8 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 09/14] ARM: i.MX: xload nand: Use final page layout from FCB Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-01 15:30 ` [PATCH 11/14] ARM: i.MX: xload nand: reset NAND before accessing it Sascha Hauer
` (3 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
fcb->EccBlock0Size and fcb->EccBlock0EccType must be extracted from
the BCH_FLASH0LAYOUT0 register, not from the BCH_FLASH0LAYOUT1 register.
As we always use the same ECC block size for both the first and the
subsequent blocks there's no functional change in this patch, it's only
for consistency.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/imx-bbu-nand-fcb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 63c81e4ed6..05bee912e4 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -1572,10 +1572,10 @@ static void imx7_fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
fl0 = readl(bch_regs + BCH_FLASH0LAYOUT0);
fcb->MetadataBytes = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
fcb->NumEccBlocksPerPage = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS);
+ fcb->EccBlock0Size = 4 * BF_VAL(fl0, BCH_FLASHLAYOUT0_DATA0_SIZE);
+ fcb->EccBlock0EccType = BF_VAL(fl0, BCH_FLASHLAYOUT0_ECC0);
fl1 = readl(bch_regs + BCH_FLASH0LAYOUT1);
- fcb->EccBlock0Size = 4 * BF_VAL(fl1, BCH_FLASHLAYOUT0_DATA0_SIZE);
- fcb->EccBlock0EccType = BF_VAL(fl1, BCH_FLASHLAYOUT0_ECC0);
fcb->EccBlockNSize = 4 * BF_VAL(fl1, BCH_FLASHLAYOUT1_DATAN_SIZE);
fcb->EccBlockNEccType = BF_VAL(fl1, BCH_FLASHLAYOUT1_ECCN);
fcb->BCHType = BF_VAL(fl1, BCH_FLASHLAYOUT1_GF13_0_GF14_1);
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 11/14] ARM: i.MX: xload nand: reset NAND before accessing it
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (9 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 10/14] imx-bbu-nand-fcb: Fix reading FCB information from BCH registers Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-01 15:30 ` [PATCH 12/14] ARM: i.MX: xload nand: Move mxs_nand_mode_fcb_62bit() to header file Sascha Hauer
` (2 subsequent siblings)
13 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
One particular NAND chip here (Toshiba TC58NVG2S0H) doesn't like it when
the ID or ONFI information is read before the NAND chip is resetted. It
works once, but with the second read the chip will not deliver data
anymore. Reset the NAND chip before accessing it.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/xload-gpmi-nand.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index af20c11fa6..7e4033d74f 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -760,6 +760,10 @@ static int mxs_nand_get_info(struct mxs_nand_info *info, void *databuf)
{
int ret, i;
+ ret = mxs_nand_reset(info, databuf);
+ if (ret)
+ return ret;
+
ret = mxs_nand_check_onfi(info, databuf);
if (ret) {
if (ret != 1)
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 12/14] ARM: i.MX: xload nand: Move mxs_nand_mode_fcb_62bit() to header file
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (10 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 11/14] ARM: i.MX: xload nand: reset NAND before accessing it Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-02 8:37 ` Marco Felsch
2022-11-01 15:30 ` [PATCH 13/14] ARM: i.MX: xload nand: Implement i.MX7 support Sascha Hauer
2022-11-01 15:30 ` [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command Sascha Hauer
13 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
mxs_nand_mode_fcb_62bit() can be shared between the regular MTD NAND
driver and the upcoming i.MX7 xload driver. Move to header file.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mtd/nand/nand_mxs.c | 34 ++--------------------------------
include/soc/imx/gpmi-nand.h | 27 +++++++++++++++++++++++++++
2 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index b162c23743..79a8fbdefa 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -1123,36 +1123,6 @@ static int mxs_nand_block_markbad(struct nand_chip *chip , loff_t ofs)
return 0;
}
-#define BCH62_WRITESIZE 1024
-#define BCH62_OOBSIZE 838
-#define BCH62_PAGESIZE (BCH62_WRITESIZE + BCH62_OOBSIZE)
-
-static void mxs_nand_mode_fcb_62bit(struct mxs_nand_info *nand_info)
-{
- void __iomem *bch_regs;
- u32 fl0, fl1;
-
- bch_regs = nand_info->bch_base;
-
- /* 8 ecc_chunks */
- fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, 7);
- /* 32 bytes for metadata */
- fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, 32);
- /* using ECC62 level to be performed */
- fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, 0x1f);
- /* 0x20 * 4 bytes of the data0 block */
- fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, 0x20);
- writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
-
- /* 1024 for data + 838 for OOB */
- fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, BCH62_PAGESIZE);
- /* using ECC62 level to be performed */
- fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, 0x1f);
- /* 0x20 * 4 bytes of the data0 block */
- fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, 0x20);
- writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
-}
-
int mxs_nand_read_fcb_bch62(unsigned int block, void *buf, size_t size)
{
struct nand_chip *chip;
@@ -1174,7 +1144,7 @@ int mxs_nand_read_fcb_bch62(unsigned int block, void *buf, size_t size)
page = block * (mtd->erasesize / mtd->writesize);
- mxs_nand_mode_fcb_62bit(nand_info);
+ mxs_nand_mode_fcb_62bit(nand_info->bch_base);
nand_read_page_op(chip, page, 0, NULL, 0);
@@ -1238,7 +1208,7 @@ int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size)
nand_info = chip->priv;
channel = nand_info->dma_channel_base;
- mxs_nand_mode_fcb_62bit(nand_info);
+ mxs_nand_mode_fcb_62bit(nand_info->bch_base);
nand_select_target(chip, 0);
diff --git a/include/soc/imx/gpmi-nand.h b/include/soc/imx/gpmi-nand.h
index f7a2caa1d6..8c30dee8ab 100644
--- a/include/soc/imx/gpmi-nand.h
+++ b/include/soc/imx/gpmi-nand.h
@@ -111,4 +111,31 @@
#define MXS_NAND_BCH_TIMEOUT 10000
+#define BCH62_WRITESIZE 1024
+#define BCH62_OOBSIZE 838
+#define BCH62_PAGESIZE (BCH62_WRITESIZE + BCH62_OOBSIZE)
+
+static void mxs_nand_mode_fcb_62bit(void __iomem *bch_regs)
+{
+ u32 fl0, fl1;
+
+ /* 8 ecc_chunks */
+ fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, 7);
+ /* 32 bytes for metadata */
+ fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, 32);
+ /* using ECC62 level to be performed */
+ fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, 0x1f);
+ /* 0x20 * 4 bytes of the data0 block */
+ fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, 0x20);
+ writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
+
+ /* 1024 for data + 838 for OOB */
+ fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, BCH62_PAGESIZE);
+ /* using ECC62 level to be performed */
+ fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, 0x1f);
+ /* 0x20 * 4 bytes of the data0 block */
+ fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, 0x20);
+ writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
+}
+
#endif /* __SOC_IMX_GPMI_NAND_H */
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 12/14] ARM: i.MX: xload nand: Move mxs_nand_mode_fcb_62bit() to header file
2022-11-01 15:30 ` [PATCH 12/14] ARM: i.MX: xload nand: Move mxs_nand_mode_fcb_62bit() to header file Sascha Hauer
@ 2022-11-02 8:37 ` Marco Felsch
0 siblings, 0 replies; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 8:37 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
Hi Sascha,
On 22-11-01, Sascha Hauer wrote:
> mxs_nand_mode_fcb_62bit() can be shared between the regular MTD NAND
> driver and the upcoming i.MX7 xload driver. Move to header file.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> drivers/mtd/nand/nand_mxs.c | 34 ++--------------------------------
> include/soc/imx/gpmi-nand.h | 27 +++++++++++++++++++++++++++
> 2 files changed, 29 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
> index b162c23743..79a8fbdefa 100644
> --- a/drivers/mtd/nand/nand_mxs.c
> +++ b/drivers/mtd/nand/nand_mxs.c
> @@ -1123,36 +1123,6 @@ static int mxs_nand_block_markbad(struct nand_chip *chip , loff_t ofs)
> return 0;
> }
>
> -#define BCH62_WRITESIZE 1024
> -#define BCH62_OOBSIZE 838
> -#define BCH62_PAGESIZE (BCH62_WRITESIZE + BCH62_OOBSIZE)
> -
> -static void mxs_nand_mode_fcb_62bit(struct mxs_nand_info *nand_info)
> -{
> - void __iomem *bch_regs;
> - u32 fl0, fl1;
> -
> - bch_regs = nand_info->bch_base;
> -
> - /* 8 ecc_chunks */
> - fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, 7);
> - /* 32 bytes for metadata */
> - fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, 32);
> - /* using ECC62 level to be performed */
> - fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, 0x1f);
> - /* 0x20 * 4 bytes of the data0 block */
> - fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, 0x20);
> - writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
> -
> - /* 1024 for data + 838 for OOB */
> - fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, BCH62_PAGESIZE);
> - /* using ECC62 level to be performed */
> - fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, 0x1f);
> - /* 0x20 * 4 bytes of the data0 block */
> - fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, 0x20);
> - writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
> -}
> -
> int mxs_nand_read_fcb_bch62(unsigned int block, void *buf, size_t size)
> {
> struct nand_chip *chip;
> @@ -1174,7 +1144,7 @@ int mxs_nand_read_fcb_bch62(unsigned int block, void *buf, size_t size)
>
> page = block * (mtd->erasesize / mtd->writesize);
>
> - mxs_nand_mode_fcb_62bit(nand_info);
> + mxs_nand_mode_fcb_62bit(nand_info->bch_base);
>
> nand_read_page_op(chip, page, 0, NULL, 0);
>
> @@ -1238,7 +1208,7 @@ int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size)
> nand_info = chip->priv;
> channel = nand_info->dma_channel_base;
>
> - mxs_nand_mode_fcb_62bit(nand_info);
> + mxs_nand_mode_fcb_62bit(nand_info->bch_base);
>
> nand_select_target(chip, 0);
>
> diff --git a/include/soc/imx/gpmi-nand.h b/include/soc/imx/gpmi-nand.h
> index f7a2caa1d6..8c30dee8ab 100644
> --- a/include/soc/imx/gpmi-nand.h
> +++ b/include/soc/imx/gpmi-nand.h
> @@ -111,4 +111,31 @@
>
> #define MXS_NAND_BCH_TIMEOUT 10000
>
> +#define BCH62_WRITESIZE 1024
> +#define BCH62_OOBSIZE 838
> +#define BCH62_PAGESIZE (BCH62_WRITESIZE + BCH62_OOBSIZE)
> +
Nit: Maybe put a small comment here so we can easily see why we are
doing this.
Regards,
Marco
> +static void mxs_nand_mode_fcb_62bit(void __iomem *bch_regs)
> +{
> + u32 fl0, fl1;
> +
> + /* 8 ecc_chunks */
> + fl0 = FIELD_PREP(BCH_FLASHLAYOUT0_NBLOCKS, 7);
> + /* 32 bytes for metadata */
> + fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_META_SIZE, 32);
> + /* using ECC62 level to be performed */
> + fl0 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT0_ECC0, 0x1f);
> + /* 0x20 * 4 bytes of the data0 block */
> + fl0 |= FIELD_PREP(BCH_FLASHLAYOUT0_DATA0_SIZE, 0x20);
> + writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
> +
> + /* 1024 for data + 838 for OOB */
> + fl1 = FIELD_PREP(BCH_FLASHLAYOUT1_PAGE_SIZE, BCH62_PAGESIZE);
> + /* using ECC62 level to be performed */
> + fl1 |= FIELD_PREP(IMX6_BCH_FLASHLAYOUT1_ECCN, 0x1f);
> + /* 0x20 * 4 bytes of the data0 block */
> + fl1 |= FIELD_PREP(BCH_FLASHLAYOUT1_DATAN_SIZE, 0x20);
> + writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
> +}
> +
> #endif /* __SOC_IMX_GPMI_NAND_H */
> --
> 2.30.2
>
>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 13/14] ARM: i.MX: xload nand: Implement i.MX7 support
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (11 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 12/14] ARM: i.MX: xload nand: Move mxs_nand_mode_fcb_62bit() to header file Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-02 8:41 ` Marco Felsch
2022-11-01 15:30 ` [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command Sascha Hauer
13 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
i.MX7 xload NAND support works like on i.MX6, but the FCB is in a
different format. The FCB page uses BCH62 ECC, has 8 ECC chunks with
128 bytes each with a resulting total page size of 1862 bytes. Also
the page data is written with a pseudo randomizer enabled.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/include/mach/imx7-regs.h | 1 +
arch/arm/mach-imx/include/mach/xload.h | 1 +
arch/arm/mach-imx/xload-gpmi-nand.c | 95 ++++++++++++++++++++--
3 files changed, 91 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-imx/include/mach/imx7-regs.h b/arch/arm/mach-imx/include/mach/imx7-regs.h
index 1ee7d86e0e..379be9e062 100644
--- a/arch/arm/mach-imx/include/mach/imx7-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx7-regs.h
@@ -118,6 +118,7 @@
#define MX7_ENET1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3E0000)
#define MX7_ENET2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3F0000)
+#define MX7_APBH_BASE 0x33000000
#define MX7_GPMI_BASE 0x33002000
#define MX7_BCH_BASE 0x33004000
diff --git a/arch/arm/mach-imx/include/mach/xload.h b/arch/arm/mach-imx/include/mach/xload.h
index 82bf663c42..ca0055aee2 100644
--- a/arch/arm/mach-imx/include/mach/xload.h
+++ b/arch/arm/mach-imx/include/mach/xload.h
@@ -12,6 +12,7 @@ int imx6_spi_start_image(int instance);
int imx6_esdhc_start_image(int instance);
int imx6_nand_start_image(void);
int imx7_esdhc_start_image(int instance);
+int imx7_nand_start_image(void);
int imx8m_esdhc_load_image(int instance, bool start);
int imx8mn_esdhc_load_image(int instance, bool start);
int imx8mp_esdhc_load_image(int instance, bool start);
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 7e4033d74f..edffd69e6b 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -13,6 +13,7 @@
#include <linux/mtd/rawnand.h>
#include <soc/imx/gpmi-nand.h>
#include <mach/imx6-regs.h>
+#include <mach/imx7-regs.h>
#include <mach/clock-imx6.h>
#include <dma/apbh-dma.h>
@@ -228,7 +229,7 @@ static uint32_t mxs_nand_aux_status_offset(void)
}
static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
- int oobsize, int pagenum, void *databuf, int raw)
+ int oobsize, int pagenum, void *databuf, int raw, bool randomizer)
{
void __iomem *bch_regs = info->bch_base;
unsigned column = 0;
@@ -332,6 +333,12 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
d->pio_words[4] = (dma_addr_t)databuf;
d->pio_words[5] = (dma_addr_t)(databuf + writesize);
+ if (randomizer) {
+ d->pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
+ GPMI_ECCCTRL_RANDOMIZER_TYPE2;
+ d->pio_words[3] |= (pagenum % 256) << 16;
+ }
+
/* Compile DMA descriptor - disable the BCH block. */
d = &info->desc[descnum++];
d->data = MXS_DMA_DESC_NAND_WAIT_4_READY |
@@ -841,7 +848,7 @@ static uint32_t calc_chksum(void *buf, size_t size)
return ~chksum;
}
-static int get_fcb(struct mxs_nand_info *info, void *databuf)
+static int imx6_get_fcb(struct mxs_nand_info *info, void *databuf)
{
int i, pagenum, ret;
uint32_t checksum;
@@ -849,13 +856,13 @@ static int get_fcb(struct mxs_nand_info *info, void *databuf)
/* First page read fails, this shouldn't be necessary */
mxs_nand_read_page(info, info->organization.pagesize,
- info->organization.oobsize, 0, databuf, 1);
+ info->organization.oobsize, 0, databuf, 1, false);
for (i = 0; i < 4; i++) {
pagenum = info->organization.pages_per_eraseblock * i;
ret = mxs_nand_read_page(info, info->organization.pagesize,
- info->organization.oobsize, pagenum, databuf, 1);
+ info->organization.oobsize, pagenum, databuf, 1, false);
if (ret)
continue;
@@ -887,6 +894,66 @@ static int get_fcb(struct mxs_nand_info *info, void *databuf)
return -EINVAL;
}
+static int imx7_get_fcb_n(struct mxs_nand_info *info, void *databuf, int num)
+{
+ int ret;
+ int flips = 0;
+ uint8_t *status;
+ int i;
+
+ ret = mxs_nand_read_page(info, BCH62_WRITESIZE, BCH62_OOBSIZE,
+ info->organization.pages_per_eraseblock * num, databuf, 0, true);
+ if (ret)
+ return ret;
+
+ /* Loop over status bytes, accumulating ECC status. */
+ status = databuf + BCH62_WRITESIZE + 32;
+
+ for (i = 0; i < 8; i++) {
+ switch (status[i]) {
+ case 0x0:
+ break;
+ case 0xff:
+ /*
+ * A status of 0xff means the chunk is erased, but due to
+ * the randomizer we see this as random data. Explicitly
+ * memset it.
+ */
+ memset(databuf + 0x80 * i, 0xff, 0x80);
+ break;
+ case 0xfe:
+ return -EBADMSG;
+ default:
+ flips += status[0];
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int imx7_get_fcb(struct mxs_nand_info *info, void *databuf)
+{
+ int i, ret;
+ struct fcb_block *fcb = &info->fcb;
+
+ mxs_nand_mode_fcb_62bit(info->bch_base);
+
+ for (i = 0; i < 4; i++) {
+ ret = imx7_get_fcb_n(info, databuf, i);
+ if (!ret)
+ break;
+ }
+
+ if (ret) {
+ pr_err("Cannot find FCB\n");
+ } else {
+ memcpy(fcb, databuf, sizeof(*fcb));
+ }
+
+ return ret;
+}
+
static int get_dbbt(struct mxs_nand_info *info, void *databuf)
{
int i, ret;
@@ -991,7 +1058,7 @@ static int read_firmware(struct mxs_nand_info *info, int startpage,
}
ret = mxs_nand_read_page(info, pagesize, oobsize,
- curpage, dest, 0);
+ curpage, dest, 0, false);
if (ret) {
pr_debug("Failed to read page %d\n", curpage);
return ret;
@@ -1012,6 +1079,7 @@ struct imx_nand_params {
struct mxs_nand_info info;
struct apbh_dma apbh;
void *sdram;
+ int (*get_fcb)(struct mxs_nand_info *info, void *databuf);
};
static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
@@ -1036,7 +1104,7 @@ static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
if (ret)
return ret;
- ret = get_fcb(info, databuf);
+ ret = params->get_fcb(info, databuf);
if (ret)
return ret;
@@ -1120,6 +1188,7 @@ int imx6_nand_start_image(void)
.apbh.regs = IOMEM(MX6_APBH_BASE_ADDR),
.apbh.id = IMX28_DMA,
.sdram = (void *)MX6_MMDC_PORT01_BASE_ADDR,
+ .get_fcb = imx6_get_fcb,
};
/* Apply ERR007117 workaround */
@@ -1127,3 +1196,17 @@ int imx6_nand_start_image(void)
return imx_nand_start_image(¶ms);
}
+
+int imx7_nand_start_image(void)
+{
+ static struct imx_nand_params params = {
+ .info.io_base = IOMEM(MX7_GPMI_BASE),
+ .info.bch_base = IOMEM(MX7_BCH_BASE),
+ .apbh.regs = IOMEM(MX7_APBH_BASE),
+ .apbh.id = IMX28_DMA,
+ .sdram = (void *)MX7_DDR_BASE_ADDR,
+ .get_fcb = imx7_get_fcb,
+ };
+
+ return imx_nand_start_image(¶ms);
+}
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 13/14] ARM: i.MX: xload nand: Implement i.MX7 support
2022-11-01 15:30 ` [PATCH 13/14] ARM: i.MX: xload nand: Implement i.MX7 support Sascha Hauer
@ 2022-11-02 8:41 ` Marco Felsch
2022-11-02 8:46 ` Sascha Hauer
0 siblings, 1 reply; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 8:41 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
Hi Sascha,
On 22-11-01, Sascha Hauer wrote:
> i.MX7 xload NAND support works like on i.MX6, but the FCB is in a
> different format. The FCB page uses BCH62 ECC, has 8 ECC chunks with
> 128 bytes each with a resulting total page size of 1862 bytes. Also
> the page data is written with a pseudo randomizer enabled.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/mach-imx/include/mach/imx7-regs.h | 1 +
> arch/arm/mach-imx/include/mach/xload.h | 1 +
> arch/arm/mach-imx/xload-gpmi-nand.c | 95 ++++++++++++++++++++--
> 3 files changed, 91 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-imx/include/mach/imx7-regs.h b/arch/arm/mach-imx/include/mach/imx7-regs.h
> index 1ee7d86e0e..379be9e062 100644
> --- a/arch/arm/mach-imx/include/mach/imx7-regs.h
> +++ b/arch/arm/mach-imx/include/mach/imx7-regs.h
> @@ -118,6 +118,7 @@
> #define MX7_ENET1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3E0000)
> #define MX7_ENET2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3F0000)
>
> +#define MX7_APBH_BASE 0x33000000
> #define MX7_GPMI_BASE 0x33002000
> #define MX7_BCH_BASE 0x33004000
>
> diff --git a/arch/arm/mach-imx/include/mach/xload.h b/arch/arm/mach-imx/include/mach/xload.h
> index 82bf663c42..ca0055aee2 100644
> --- a/arch/arm/mach-imx/include/mach/xload.h
> +++ b/arch/arm/mach-imx/include/mach/xload.h
> @@ -12,6 +12,7 @@ int imx6_spi_start_image(int instance);
> int imx6_esdhc_start_image(int instance);
> int imx6_nand_start_image(void);
> int imx7_esdhc_start_image(int instance);
> +int imx7_nand_start_image(void);
> int imx8m_esdhc_load_image(int instance, bool start);
> int imx8mn_esdhc_load_image(int instance, bool start);
> int imx8mp_esdhc_load_image(int instance, bool start);
> diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
> index 7e4033d74f..edffd69e6b 100644
> --- a/arch/arm/mach-imx/xload-gpmi-nand.c
> +++ b/arch/arm/mach-imx/xload-gpmi-nand.c
> @@ -13,6 +13,7 @@
> #include <linux/mtd/rawnand.h>
> #include <soc/imx/gpmi-nand.h>
> #include <mach/imx6-regs.h>
> +#include <mach/imx7-regs.h>
> #include <mach/clock-imx6.h>
> #include <dma/apbh-dma.h>
>
> @@ -228,7 +229,7 @@ static uint32_t mxs_nand_aux_status_offset(void)
> }
>
> static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> - int oobsize, int pagenum, void *databuf, int raw)
> + int oobsize, int pagenum, void *databuf, int raw, bool randomizer)
Here the change comes, so this anwers my question.
Regards,
Marco
> {
> void __iomem *bch_regs = info->bch_base;
> unsigned column = 0;
> @@ -332,6 +333,12 @@ static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> d->pio_words[4] = (dma_addr_t)databuf;
> d->pio_words[5] = (dma_addr_t)(databuf + writesize);
>
> + if (randomizer) {
> + d->pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
> + GPMI_ECCCTRL_RANDOMIZER_TYPE2;
> + d->pio_words[3] |= (pagenum % 256) << 16;
> + }
> +
> /* Compile DMA descriptor - disable the BCH block. */
> d = &info->desc[descnum++];
> d->data = MXS_DMA_DESC_NAND_WAIT_4_READY |
> @@ -841,7 +848,7 @@ static uint32_t calc_chksum(void *buf, size_t size)
> return ~chksum;
> }
>
> -static int get_fcb(struct mxs_nand_info *info, void *databuf)
> +static int imx6_get_fcb(struct mxs_nand_info *info, void *databuf)
> {
> int i, pagenum, ret;
> uint32_t checksum;
> @@ -849,13 +856,13 @@ static int get_fcb(struct mxs_nand_info *info, void *databuf)
>
> /* First page read fails, this shouldn't be necessary */
> mxs_nand_read_page(info, info->organization.pagesize,
> - info->organization.oobsize, 0, databuf, 1);
> + info->organization.oobsize, 0, databuf, 1, false);
>
> for (i = 0; i < 4; i++) {
> pagenum = info->organization.pages_per_eraseblock * i;
>
> ret = mxs_nand_read_page(info, info->organization.pagesize,
> - info->organization.oobsize, pagenum, databuf, 1);
> + info->organization.oobsize, pagenum, databuf, 1, false);
> if (ret)
> continue;
>
> @@ -887,6 +894,66 @@ static int get_fcb(struct mxs_nand_info *info, void *databuf)
> return -EINVAL;
> }
>
> +static int imx7_get_fcb_n(struct mxs_nand_info *info, void *databuf, int num)
> +{
> + int ret;
> + int flips = 0;
> + uint8_t *status;
> + int i;
> +
> + ret = mxs_nand_read_page(info, BCH62_WRITESIZE, BCH62_OOBSIZE,
> + info->organization.pages_per_eraseblock * num, databuf, 0, true);
> + if (ret)
> + return ret;
> +
> + /* Loop over status bytes, accumulating ECC status. */
> + status = databuf + BCH62_WRITESIZE + 32;
> +
> + for (i = 0; i < 8; i++) {
> + switch (status[i]) {
> + case 0x0:
> + break;
> + case 0xff:
> + /*
> + * A status of 0xff means the chunk is erased, but due to
> + * the randomizer we see this as random data. Explicitly
> + * memset it.
> + */
> + memset(databuf + 0x80 * i, 0xff, 0x80);
> + break;
> + case 0xfe:
> + return -EBADMSG;
> + default:
> + flips += status[0];
> + break;
> + }
> + }
> +
> + return ret;
> +}
> +
> +static int imx7_get_fcb(struct mxs_nand_info *info, void *databuf)
> +{
> + int i, ret;
> + struct fcb_block *fcb = &info->fcb;
> +
> + mxs_nand_mode_fcb_62bit(info->bch_base);
> +
> + for (i = 0; i < 4; i++) {
> + ret = imx7_get_fcb_n(info, databuf, i);
> + if (!ret)
> + break;
> + }
> +
> + if (ret) {
> + pr_err("Cannot find FCB\n");
> + } else {
> + memcpy(fcb, databuf, sizeof(*fcb));
> + }
> +
> + return ret;
> +}
> +
> static int get_dbbt(struct mxs_nand_info *info, void *databuf)
> {
> int i, ret;
> @@ -991,7 +1058,7 @@ static int read_firmware(struct mxs_nand_info *info, int startpage,
> }
>
> ret = mxs_nand_read_page(info, pagesize, oobsize,
> - curpage, dest, 0);
> + curpage, dest, 0, false);
> if (ret) {
> pr_debug("Failed to read page %d\n", curpage);
> return ret;
> @@ -1012,6 +1079,7 @@ struct imx_nand_params {
> struct mxs_nand_info info;
> struct apbh_dma apbh;
> void *sdram;
> + int (*get_fcb)(struct mxs_nand_info *info, void *databuf);
> };
>
> static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
> @@ -1036,7 +1104,7 @@ static int __maybe_unused imx6_nand_load_image(struct imx_nand_params *params,
> if (ret)
> return ret;
>
> - ret = get_fcb(info, databuf);
> + ret = params->get_fcb(info, databuf);
> if (ret)
> return ret;
>
> @@ -1120,6 +1188,7 @@ int imx6_nand_start_image(void)
> .apbh.regs = IOMEM(MX6_APBH_BASE_ADDR),
> .apbh.id = IMX28_DMA,
> .sdram = (void *)MX6_MMDC_PORT01_BASE_ADDR,
> + .get_fcb = imx6_get_fcb,
> };
>
> /* Apply ERR007117 workaround */
> @@ -1127,3 +1196,17 @@ int imx6_nand_start_image(void)
>
> return imx_nand_start_image(¶ms);
> }
> +
> +int imx7_nand_start_image(void)
> +{
> + static struct imx_nand_params params = {
> + .info.io_base = IOMEM(MX7_GPMI_BASE),
> + .info.bch_base = IOMEM(MX7_BCH_BASE),
> + .apbh.regs = IOMEM(MX7_APBH_BASE),
> + .apbh.id = IMX28_DMA,
> + .sdram = (void *)MX7_DDR_BASE_ADDR,
> + .get_fcb = imx7_get_fcb,
> + };
> +
> + return imx_nand_start_image(¶ms);
> +}
> --
> 2.30.2
>
>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 13/14] ARM: i.MX: xload nand: Implement i.MX7 support
2022-11-02 8:41 ` Marco Felsch
@ 2022-11-02 8:46 ` Sascha Hauer
0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-02 8:46 UTC (permalink / raw)
To: Marco Felsch; +Cc: Barebox List
On Wed, Nov 02, 2022 at 09:41:18AM +0100, Marco Felsch wrote:
> Hi Sascha,
>
> On 22-11-01, Sascha Hauer wrote:
> > i.MX7 xload NAND support works like on i.MX6, but the FCB is in a
> > different format. The FCB page uses BCH62 ECC, has 8 ECC chunks with
> > 128 bytes each with a resulting total page size of 1862 bytes. Also
> > the page data is written with a pseudo randomizer enabled.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> > arch/arm/mach-imx/include/mach/imx7-regs.h | 1 +
> > arch/arm/mach-imx/include/mach/xload.h | 1 +
> > arch/arm/mach-imx/xload-gpmi-nand.c | 95 ++++++++++++++++++++--
> > 3 files changed, 91 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/arm/mach-imx/include/mach/imx7-regs.h b/arch/arm/mach-imx/include/mach/imx7-regs.h
> > index 1ee7d86e0e..379be9e062 100644
> > --- a/arch/arm/mach-imx/include/mach/imx7-regs.h
> > +++ b/arch/arm/mach-imx/include/mach/imx7-regs.h
> > @@ -118,6 +118,7 @@
> > #define MX7_ENET1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3E0000)
> > #define MX7_ENET2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3F0000)
> >
> > +#define MX7_APBH_BASE 0x33000000
> > #define MX7_GPMI_BASE 0x33002000
> > #define MX7_BCH_BASE 0x33004000
> >
> > diff --git a/arch/arm/mach-imx/include/mach/xload.h b/arch/arm/mach-imx/include/mach/xload.h
> > index 82bf663c42..ca0055aee2 100644
> > --- a/arch/arm/mach-imx/include/mach/xload.h
> > +++ b/arch/arm/mach-imx/include/mach/xload.h
> > @@ -12,6 +12,7 @@ int imx6_spi_start_image(int instance);
> > int imx6_esdhc_start_image(int instance);
> > int imx6_nand_start_image(void);
> > int imx7_esdhc_start_image(int instance);
> > +int imx7_nand_start_image(void);
> > int imx8m_esdhc_load_image(int instance, bool start);
> > int imx8mn_esdhc_load_image(int instance, bool start);
> > int imx8mp_esdhc_load_image(int instance, bool start);
> > diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
> > index 7e4033d74f..edffd69e6b 100644
> > --- a/arch/arm/mach-imx/xload-gpmi-nand.c
> > +++ b/arch/arm/mach-imx/xload-gpmi-nand.c
> > @@ -13,6 +13,7 @@
> > #include <linux/mtd/rawnand.h>
> > #include <soc/imx/gpmi-nand.h>
> > #include <mach/imx6-regs.h>
> > +#include <mach/imx7-regs.h>
> > #include <mach/clock-imx6.h>
> > #include <dma/apbh-dma.h>
> >
> > @@ -228,7 +229,7 @@ static uint32_t mxs_nand_aux_status_offset(void)
> > }
> >
> > static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
> > - int oobsize, int pagenum, void *databuf, int raw)
> > + int oobsize, int pagenum, void *databuf, int raw, bool randomizer)
>
> Here the change comes, so this anwers my question.
Yes, moved the offending hunk here.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command
2022-11-01 15:30 [PATCH 00/14] Add i.MX7 NAND xload support Sascha Hauer
` (12 preceding siblings ...)
2022-11-01 15:30 ` [PATCH 13/14] ARM: i.MX: xload nand: Implement i.MX7 support Sascha Hauer
@ 2022-11-01 15:30 ` Sascha Hauer
2022-11-02 8:44 ` Marco Felsch
13 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-01 15:30 UTC (permalink / raw)
To: Barebox List
The FCB on NAND has a special page layout and thus can't be read with
the normal MTD driver. Add a fcb command for printing information about
the installed FCB on the console.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/Kconfig | 9 ++
common/imx-bbu-nand-fcb.c | 195 ++++++++++++++++++++++++++++----------
2 files changed, 153 insertions(+), 51 deletions(-)
diff --git a/commands/Kconfig b/commands/Kconfig
index 9894ecb9aa..cab72b9226 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -326,6 +326,15 @@ config CMD_SLICE
command can be used to print informations about slices and also to manipulate
them on the command line for debugging purposes.
+config CMD_FCB
+ depends on BAREBOX_UPDATE_IMX_NAND_FCB
+ tristate
+ prompt "fcb"
+ help
+ Several i.MX SoCs booting from NAND flash need a so called Flash Control Block
+ at the beginning of the NAND device. The fcb command prints information about
+ the FCB.
+
# end Information commands
endmenu
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 05bee912e4..39425c7fc3 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -14,6 +14,8 @@
#include <linux/sizes.h>
#include <bbu.h>
#include <fs.h>
+#include <command.h>
+#include <complete.h>
#include <linux/mtd/mtd-abi.h>
#include <linux/mtd/nand_mxs.h>
#include <linux/mtd/mtd.h>
@@ -284,57 +286,57 @@ static __maybe_unused void dump_fcb(void *buf)
{
struct fcb_block *fcb = buf;
- pr_debug("Checksum: 0x%08x\n", fcb->Checksum);
- pr_debug("FingerPrint: 0x%08x\n", fcb->FingerPrint);
- pr_debug("Version: 0x%08x\n", fcb->Version);
- pr_debug("DataSetup: 0x%02x\n", fcb->DataSetup);
- pr_debug("DataHold: 0x%02x\n", fcb->DataHold);
- pr_debug("AddressSetup: 0x%02x\n", fcb->AddressSetup);
- pr_debug("DSAMPLE_TIME: 0x%02x\n", fcb->DSAMPLE_TIME);
- pr_debug("NandTimingState: 0x%02x\n", fcb->NandTimingState);
- pr_debug("REA: 0x%02x\n", fcb->REA);
- pr_debug("RLOH: 0x%02x\n", fcb->RLOH);
- pr_debug("RHOH: 0x%02x\n", fcb->RHOH);
- pr_debug("PageDataSize: 0x%08x\n", fcb->PageDataSize);
- pr_debug("TotalPageSize: 0x%08x\n", fcb->TotalPageSize);
- pr_debug("SectorsPerBlock: 0x%08x\n", fcb->SectorsPerBlock);
- pr_debug("NumberOfNANDs: 0x%08x\n", fcb->NumberOfNANDs);
- pr_debug("TotalInternalDie: 0x%08x\n", fcb->TotalInternalDie);
- pr_debug("CellType: 0x%08x\n", fcb->CellType);
- pr_debug("EccBlockNEccType: 0x%08x\n", fcb->EccBlockNEccType);
- pr_debug("EccBlock0Size: 0x%08x\n", fcb->EccBlock0Size);
- pr_debug("EccBlockNSize: 0x%08x\n", fcb->EccBlockNSize);
- pr_debug("EccBlock0EccType: 0x%08x\n", fcb->EccBlock0EccType);
- pr_debug("MetadataBytes: 0x%08x\n", fcb->MetadataBytes);
- pr_debug("NumEccBlocksPerPage: 0x%08x\n", fcb->NumEccBlocksPerPage);
- pr_debug("EccBlockNEccLevelSDK: 0x%08x\n", fcb->EccBlockNEccLevelSDK);
- pr_debug("EccBlock0SizeSDK: 0x%08x\n", fcb->EccBlock0SizeSDK);
- pr_debug("EccBlockNSizeSDK: 0x%08x\n", fcb->EccBlockNSizeSDK);
- pr_debug("EccBlock0EccLevelSDK: 0x%08x\n", fcb->EccBlock0EccLevelSDK);
- pr_debug("NumEccBlocksPerPageSDK: 0x%08x\n", fcb->NumEccBlocksPerPageSDK);
- pr_debug("MetadataBytesSDK: 0x%08x\n", fcb->MetadataBytesSDK);
- pr_debug("EraseThreshold: 0x%08x\n", fcb->EraseThreshold);
- pr_debug("BootPatch: 0x%08x\n", fcb->BootPatch);
- pr_debug("PatchSectors: 0x%08x\n", fcb->PatchSectors);
- pr_debug("Firmware1_startingPage: 0x%08x\n", fcb->Firmware1_startingPage);
- pr_debug("Firmware2_startingPage: 0x%08x\n", fcb->Firmware2_startingPage);
- pr_debug("PagesInFirmware1: 0x%08x\n", fcb->PagesInFirmware1);
- pr_debug("PagesInFirmware2: 0x%08x\n", fcb->PagesInFirmware2);
- pr_debug("DBBTSearchAreaStartAddress: 0x%08x\n", fcb->DBBTSearchAreaStartAddress);
- pr_debug("BadBlockMarkerByte: 0x%08x\n", fcb->BadBlockMarkerByte);
- pr_debug("BadBlockMarkerStartBit: 0x%08x\n", fcb->BadBlockMarkerStartBit);
- pr_debug("BBMarkerPhysicalOffset: 0x%08x\n", fcb->BBMarkerPhysicalOffset);
- pr_debug("BCHType: 0x%08x\n", fcb->BCHType);
- pr_debug("TMTiming2_ReadLatency: 0x%08x\n", fcb->TMTiming2_ReadLatency);
- pr_debug("TMTiming2_PreambleDelay: 0x%08x\n", fcb->TMTiming2_PreambleDelay);
- pr_debug("TMTiming2_CEDelay: 0x%08x\n", fcb->TMTiming2_CEDelay);
- pr_debug("TMTiming2_PostambleDelay: 0x%08x\n", fcb->TMTiming2_PostambleDelay);
- pr_debug("TMTiming2_CmdAddPause: 0x%08x\n", fcb->TMTiming2_CmdAddPause);
- pr_debug("TMTiming2_DataPause: 0x%08x\n", fcb->TMTiming2_DataPause);
- pr_debug("TMSpeed: 0x%08x\n", fcb->TMSpeed);
- pr_debug("TMTiming1_BusyTimeout: 0x%08x\n", fcb->TMTiming1_BusyTimeout);
- pr_debug("DISBBM: 0x%08x\n", fcb->DISBBM);
- pr_debug("BBMarkerPhysOfsInSpareData: 0x%08x\n", fcb->BBMarkerPhysicalOffsetInSpareData);
+ printf("Checksum: 0x%08x\n", fcb->Checksum);
+ printf("FingerPrint: 0x%08x\n", fcb->FingerPrint);
+ printf("Version: 0x%08x\n", fcb->Version);
+ printf("DataSetup: 0x%02x\n", fcb->DataSetup);
+ printf("DataHold: 0x%02x\n", fcb->DataHold);
+ printf("AddressSetup: 0x%02x\n", fcb->AddressSetup);
+ printf("DSAMPLE_TIME: 0x%02x\n", fcb->DSAMPLE_TIME);
+ printf("NandTimingState: 0x%02x\n", fcb->NandTimingState);
+ printf("REA: 0x%02x\n", fcb->REA);
+ printf("RLOH: 0x%02x\n", fcb->RLOH);
+ printf("RHOH: 0x%02x\n", fcb->RHOH);
+ printf("PageDataSize: 0x%08x\n", fcb->PageDataSize);
+ printf("TotalPageSize: 0x%08x\n", fcb->TotalPageSize);
+ printf("SectorsPerBlock: 0x%08x\n", fcb->SectorsPerBlock);
+ printf("NumberOfNANDs: 0x%08x\n", fcb->NumberOfNANDs);
+ printf("TotalInternalDie: 0x%08x\n", fcb->TotalInternalDie);
+ printf("CellType: 0x%08x\n", fcb->CellType);
+ printf("EccBlockNEccType: 0x%08x\n", fcb->EccBlockNEccType);
+ printf("EccBlock0Size: 0x%08x\n", fcb->EccBlock0Size);
+ printf("EccBlockNSize: 0x%08x\n", fcb->EccBlockNSize);
+ printf("EccBlock0EccType: 0x%08x\n", fcb->EccBlock0EccType);
+ printf("MetadataBytes: 0x%08x\n", fcb->MetadataBytes);
+ printf("NumEccBlocksPerPage: 0x%08x\n", fcb->NumEccBlocksPerPage);
+ printf("EccBlockNEccLevelSDK: 0x%08x\n", fcb->EccBlockNEccLevelSDK);
+ printf("EccBlock0SizeSDK: 0x%08x\n", fcb->EccBlock0SizeSDK);
+ printf("EccBlockNSizeSDK: 0x%08x\n", fcb->EccBlockNSizeSDK);
+ printf("EccBlock0EccLevelSDK: 0x%08x\n", fcb->EccBlock0EccLevelSDK);
+ printf("NumEccBlocksPerPageSDK: 0x%08x\n", fcb->NumEccBlocksPerPageSDK);
+ printf("MetadataBytesSDK: 0x%08x\n", fcb->MetadataBytesSDK);
+ printf("EraseThreshold: 0x%08x\n", fcb->EraseThreshold);
+ printf("BootPatch: 0x%08x\n", fcb->BootPatch);
+ printf("PatchSectors: 0x%08x\n", fcb->PatchSectors);
+ printf("Firmware1_startingPage: 0x%08x\n", fcb->Firmware1_startingPage);
+ printf("Firmware2_startingPage: 0x%08x\n", fcb->Firmware2_startingPage);
+ printf("PagesInFirmware1: 0x%08x\n", fcb->PagesInFirmware1);
+ printf("PagesInFirmware2: 0x%08x\n", fcb->PagesInFirmware2);
+ printf("DBBTSearchAreaStartAddress: 0x%08x\n", fcb->DBBTSearchAreaStartAddress);
+ printf("BadBlockMarkerByte: 0x%08x\n", fcb->BadBlockMarkerByte);
+ printf("BadBlockMarkerStartBit: 0x%08x\n", fcb->BadBlockMarkerStartBit);
+ printf("BBMarkerPhysicalOffset: 0x%08x\n", fcb->BBMarkerPhysicalOffset);
+ printf("BCHType: 0x%08x\n", fcb->BCHType);
+ printf("TMTiming2_ReadLatency: 0x%08x\n", fcb->TMTiming2_ReadLatency);
+ printf("TMTiming2_PreambleDelay: 0x%08x\n", fcb->TMTiming2_PreambleDelay);
+ printf("TMTiming2_CEDelay: 0x%08x\n", fcb->TMTiming2_CEDelay);
+ printf("TMTiming2_PostambleDelay: 0x%08x\n", fcb->TMTiming2_PostambleDelay);
+ printf("TMTiming2_CmdAddPause: 0x%08x\n", fcb->TMTiming2_CmdAddPause);
+ printf("TMTiming2_DataPause: 0x%08x\n", fcb->TMTiming2_DataPause);
+ printf("TMSpeed: 0x%08x\n", fcb->TMSpeed);
+ printf("TMTiming1_BusyTimeout: 0x%08x\n", fcb->TMTiming1_BusyTimeout);
+ printf("DISBBM: 0x%08x\n", fcb->DISBBM);
+ printf("BBMarkerPhysOfsInSpareData: 0x%08x\n", fcb->BBMarkerPhysicalOffsetInSpareData);
}
static __maybe_unused ssize_t raw_read_page(struct mtd_info *mtd, void *dst, loff_t offset)
@@ -1625,3 +1627,94 @@ int imx7_bbu_nand_register_handler(const char *name, unsigned long flags)
return ret;
}
#endif
+
+static void dump_fcb_n(struct fcb_block **fcbs, int n)
+{
+ int i;
+
+ if (!n || !fcbs[n])
+ goto skip_compare;
+
+ for (i = 0; i < n; i++) {
+ if (!fcbs[i] || !fcbs[n])
+ continue;
+
+ if (!memcmp(fcbs[i], fcbs[n], sizeof(struct fcb_block))) {
+ printf("FCB block#%d: same as FCB block#%d\n", n, i);
+ return;
+ }
+ }
+
+skip_compare:
+ if (fcbs[n]) {
+ printf("FCB block#%d:\n", n);
+ dump_fcb(fcbs[n]);
+ } else {
+ printf("FCB block#%d: NULL\n", n);
+ }
+}
+
+#ifdef CONFIG_ARCH_IMX28
+static int fcb_read(struct mtd_info *mtd, int block, struct fcb_block **retfcb)
+{
+ return fcb_read_hamming_13_8(mtd, block, retfcb);
+}
+#else
+static int fcb_read(struct mtd_info *mtd, int block, struct fcb_block **retfcb)
+{
+ if (cpu_is_mx7())
+ return imx7_fcb_read(mtd, block, retfcb);
+ else if (fcb_is_bch_encoded())
+ return fcb_read_bch(mtd, block, retfcb);
+ else
+ return fcb_read_hamming_13_8(mtd, block, retfcb);
+}
+#endif
+
+static int cmd_fcb(int argc, char *argv[])
+{
+ struct cdev *cdev;
+ struct mtd_info *mtd;
+ struct fcb_block *fcb[4] = {};
+ int i, ret;
+
+ cdev = cdev_open_by_name("nand0", O_RDONLY);
+ if (!cdev) {
+ printf("Cannot open nand0\n");
+ return COMMAND_ERROR;
+ }
+
+ mtd = cdev->mtd;
+ if (!mtd) {
+ ret = COMMAND_ERROR;
+ goto out;
+ }
+
+ for (i = 0; i < 4; i++)
+ fcb_read(mtd, i, &fcb[i]);
+
+ for (i = 0; i < 4; i++)
+ dump_fcb_n(fcb, i);
+
+ for (i = 0; i < 4; i++)
+ free(fcb[i]);
+
+ ret = 0;
+
+out:
+ cdev_close(cdev);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(fcb)
+BAREBOX_CMD_HELP_TEXT("Dump FCB as found on /dev/nand0")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(fcb)
+ .cmd = cmd_fcb,
+ BAREBOX_CMD_DESC("Dump Flash Control Block (FCB)")
+ BAREBOX_CMD_GROUP(CMD_GRP_MISC)
+ BAREBOX_CMD_HELP(cmd_fcb_help)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+BAREBOX_CMD_END
--
2.30.2
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command
2022-11-01 15:30 ` [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command Sascha Hauer
@ 2022-11-02 8:44 ` Marco Felsch
2022-11-02 10:55 ` Sascha Hauer
0 siblings, 1 reply; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 8:44 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
Hi Sascha,
On 22-11-01, Sascha Hauer wrote:
> The FCB on NAND has a special page layout and thus can't be read with
> the normal MTD driver. Add a fcb command for printing information about
> the installed FCB on the console.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> commands/Kconfig | 9 ++
> common/imx-bbu-nand-fcb.c | 195 ++++++++++++++++++++++++++++----------
> 2 files changed, 153 insertions(+), 51 deletions(-)
>
> diff --git a/commands/Kconfig b/commands/Kconfig
> index 9894ecb9aa..cab72b9226 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -326,6 +326,15 @@ config CMD_SLICE
> command can be used to print informations about slices and also to manipulate
> them on the command line for debugging purposes.
>
> +config CMD_FCB
> + depends on BAREBOX_UPDATE_IMX_NAND_FCB
> + tristate
> + prompt "fcb"
> + help
> + Several i.MX SoCs booting from NAND flash need a so called Flash Control Block
> + at the beginning of the NAND device. The fcb command prints information about
> + the FCB.
> +
> # end Information commands
> endmenu
>
> diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
> index 05bee912e4..39425c7fc3 100644
> --- a/common/imx-bbu-nand-fcb.c
> +++ b/common/imx-bbu-nand-fcb.c
> @@ -14,6 +14,8 @@
> #include <linux/sizes.h>
> #include <bbu.h>
> #include <fs.h>
> +#include <command.h>
> +#include <complete.h>
> #include <linux/mtd/mtd-abi.h>
> #include <linux/mtd/nand_mxs.h>
> #include <linux/mtd/mtd.h>
> @@ -284,57 +286,57 @@ static __maybe_unused void dump_fcb(void *buf)
> {
> struct fcb_block *fcb = buf;
>
> - pr_debug("Checksum: 0x%08x\n", fcb->Checksum);
> - pr_debug("FingerPrint: 0x%08x\n", fcb->FingerPrint);
> - pr_debug("Version: 0x%08x\n", fcb->Version);
> - pr_debug("DataSetup: 0x%02x\n", fcb->DataSetup);
> - pr_debug("DataHold: 0x%02x\n", fcb->DataHold);
> - pr_debug("AddressSetup: 0x%02x\n", fcb->AddressSetup);
> - pr_debug("DSAMPLE_TIME: 0x%02x\n", fcb->DSAMPLE_TIME);
> - pr_debug("NandTimingState: 0x%02x\n", fcb->NandTimingState);
> - pr_debug("REA: 0x%02x\n", fcb->REA);
> - pr_debug("RLOH: 0x%02x\n", fcb->RLOH);
> - pr_debug("RHOH: 0x%02x\n", fcb->RHOH);
> - pr_debug("PageDataSize: 0x%08x\n", fcb->PageDataSize);
> - pr_debug("TotalPageSize: 0x%08x\n", fcb->TotalPageSize);
> - pr_debug("SectorsPerBlock: 0x%08x\n", fcb->SectorsPerBlock);
> - pr_debug("NumberOfNANDs: 0x%08x\n", fcb->NumberOfNANDs);
> - pr_debug("TotalInternalDie: 0x%08x\n", fcb->TotalInternalDie);
> - pr_debug("CellType: 0x%08x\n", fcb->CellType);
> - pr_debug("EccBlockNEccType: 0x%08x\n", fcb->EccBlockNEccType);
> - pr_debug("EccBlock0Size: 0x%08x\n", fcb->EccBlock0Size);
> - pr_debug("EccBlockNSize: 0x%08x\n", fcb->EccBlockNSize);
> - pr_debug("EccBlock0EccType: 0x%08x\n", fcb->EccBlock0EccType);
> - pr_debug("MetadataBytes: 0x%08x\n", fcb->MetadataBytes);
> - pr_debug("NumEccBlocksPerPage: 0x%08x\n", fcb->NumEccBlocksPerPage);
> - pr_debug("EccBlockNEccLevelSDK: 0x%08x\n", fcb->EccBlockNEccLevelSDK);
> - pr_debug("EccBlock0SizeSDK: 0x%08x\n", fcb->EccBlock0SizeSDK);
> - pr_debug("EccBlockNSizeSDK: 0x%08x\n", fcb->EccBlockNSizeSDK);
> - pr_debug("EccBlock0EccLevelSDK: 0x%08x\n", fcb->EccBlock0EccLevelSDK);
> - pr_debug("NumEccBlocksPerPageSDK: 0x%08x\n", fcb->NumEccBlocksPerPageSDK);
> - pr_debug("MetadataBytesSDK: 0x%08x\n", fcb->MetadataBytesSDK);
> - pr_debug("EraseThreshold: 0x%08x\n", fcb->EraseThreshold);
> - pr_debug("BootPatch: 0x%08x\n", fcb->BootPatch);
> - pr_debug("PatchSectors: 0x%08x\n", fcb->PatchSectors);
> - pr_debug("Firmware1_startingPage: 0x%08x\n", fcb->Firmware1_startingPage);
> - pr_debug("Firmware2_startingPage: 0x%08x\n", fcb->Firmware2_startingPage);
> - pr_debug("PagesInFirmware1: 0x%08x\n", fcb->PagesInFirmware1);
> - pr_debug("PagesInFirmware2: 0x%08x\n", fcb->PagesInFirmware2);
> - pr_debug("DBBTSearchAreaStartAddress: 0x%08x\n", fcb->DBBTSearchAreaStartAddress);
> - pr_debug("BadBlockMarkerByte: 0x%08x\n", fcb->BadBlockMarkerByte);
> - pr_debug("BadBlockMarkerStartBit: 0x%08x\n", fcb->BadBlockMarkerStartBit);
> - pr_debug("BBMarkerPhysicalOffset: 0x%08x\n", fcb->BBMarkerPhysicalOffset);
> - pr_debug("BCHType: 0x%08x\n", fcb->BCHType);
> - pr_debug("TMTiming2_ReadLatency: 0x%08x\n", fcb->TMTiming2_ReadLatency);
> - pr_debug("TMTiming2_PreambleDelay: 0x%08x\n", fcb->TMTiming2_PreambleDelay);
> - pr_debug("TMTiming2_CEDelay: 0x%08x\n", fcb->TMTiming2_CEDelay);
> - pr_debug("TMTiming2_PostambleDelay: 0x%08x\n", fcb->TMTiming2_PostambleDelay);
> - pr_debug("TMTiming2_CmdAddPause: 0x%08x\n", fcb->TMTiming2_CmdAddPause);
> - pr_debug("TMTiming2_DataPause: 0x%08x\n", fcb->TMTiming2_DataPause);
> - pr_debug("TMSpeed: 0x%08x\n", fcb->TMSpeed);
> - pr_debug("TMTiming1_BusyTimeout: 0x%08x\n", fcb->TMTiming1_BusyTimeout);
> - pr_debug("DISBBM: 0x%08x\n", fcb->DISBBM);
> - pr_debug("BBMarkerPhysOfsInSpareData: 0x%08x\n", fcb->BBMarkerPhysicalOffsetInSpareData);
> + printf("Checksum: 0x%08x\n", fcb->Checksum);
> + printf("FingerPrint: 0x%08x\n", fcb->FingerPrint);
> + printf("Version: 0x%08x\n", fcb->Version);
> + printf("DataSetup: 0x%02x\n", fcb->DataSetup);
> + printf("DataHold: 0x%02x\n", fcb->DataHold);
> + printf("AddressSetup: 0x%02x\n", fcb->AddressSetup);
> + printf("DSAMPLE_TIME: 0x%02x\n", fcb->DSAMPLE_TIME);
> + printf("NandTimingState: 0x%02x\n", fcb->NandTimingState);
> + printf("REA: 0x%02x\n", fcb->REA);
> + printf("RLOH: 0x%02x\n", fcb->RLOH);
> + printf("RHOH: 0x%02x\n", fcb->RHOH);
> + printf("PageDataSize: 0x%08x\n", fcb->PageDataSize);
> + printf("TotalPageSize: 0x%08x\n", fcb->TotalPageSize);
> + printf("SectorsPerBlock: 0x%08x\n", fcb->SectorsPerBlock);
> + printf("NumberOfNANDs: 0x%08x\n", fcb->NumberOfNANDs);
> + printf("TotalInternalDie: 0x%08x\n", fcb->TotalInternalDie);
> + printf("CellType: 0x%08x\n", fcb->CellType);
> + printf("EccBlockNEccType: 0x%08x\n", fcb->EccBlockNEccType);
> + printf("EccBlock0Size: 0x%08x\n", fcb->EccBlock0Size);
> + printf("EccBlockNSize: 0x%08x\n", fcb->EccBlockNSize);
> + printf("EccBlock0EccType: 0x%08x\n", fcb->EccBlock0EccType);
> + printf("MetadataBytes: 0x%08x\n", fcb->MetadataBytes);
> + printf("NumEccBlocksPerPage: 0x%08x\n", fcb->NumEccBlocksPerPage);
> + printf("EccBlockNEccLevelSDK: 0x%08x\n", fcb->EccBlockNEccLevelSDK);
> + printf("EccBlock0SizeSDK: 0x%08x\n", fcb->EccBlock0SizeSDK);
> + printf("EccBlockNSizeSDK: 0x%08x\n", fcb->EccBlockNSizeSDK);
> + printf("EccBlock0EccLevelSDK: 0x%08x\n", fcb->EccBlock0EccLevelSDK);
> + printf("NumEccBlocksPerPageSDK: 0x%08x\n", fcb->NumEccBlocksPerPageSDK);
> + printf("MetadataBytesSDK: 0x%08x\n", fcb->MetadataBytesSDK);
> + printf("EraseThreshold: 0x%08x\n", fcb->EraseThreshold);
> + printf("BootPatch: 0x%08x\n", fcb->BootPatch);
> + printf("PatchSectors: 0x%08x\n", fcb->PatchSectors);
> + printf("Firmware1_startingPage: 0x%08x\n", fcb->Firmware1_startingPage);
> + printf("Firmware2_startingPage: 0x%08x\n", fcb->Firmware2_startingPage);
> + printf("PagesInFirmware1: 0x%08x\n", fcb->PagesInFirmware1);
> + printf("PagesInFirmware2: 0x%08x\n", fcb->PagesInFirmware2);
> + printf("DBBTSearchAreaStartAddress: 0x%08x\n", fcb->DBBTSearchAreaStartAddress);
> + printf("BadBlockMarkerByte: 0x%08x\n", fcb->BadBlockMarkerByte);
> + printf("BadBlockMarkerStartBit: 0x%08x\n", fcb->BadBlockMarkerStartBit);
> + printf("BBMarkerPhysicalOffset: 0x%08x\n", fcb->BBMarkerPhysicalOffset);
> + printf("BCHType: 0x%08x\n", fcb->BCHType);
> + printf("TMTiming2_ReadLatency: 0x%08x\n", fcb->TMTiming2_ReadLatency);
> + printf("TMTiming2_PreambleDelay: 0x%08x\n", fcb->TMTiming2_PreambleDelay);
> + printf("TMTiming2_CEDelay: 0x%08x\n", fcb->TMTiming2_CEDelay);
> + printf("TMTiming2_PostambleDelay: 0x%08x\n", fcb->TMTiming2_PostambleDelay);
> + printf("TMTiming2_CmdAddPause: 0x%08x\n", fcb->TMTiming2_CmdAddPause);
> + printf("TMTiming2_DataPause: 0x%08x\n", fcb->TMTiming2_DataPause);
> + printf("TMSpeed: 0x%08x\n", fcb->TMSpeed);
> + printf("TMTiming1_BusyTimeout: 0x%08x\n", fcb->TMTiming1_BusyTimeout);
> + printf("DISBBM: 0x%08x\n", fcb->DISBBM);
> + printf("BBMarkerPhysOfsInSpareData: 0x%08x\n", fcb->BBMarkerPhysicalOffsetInSpareData);
> }
>
> static __maybe_unused ssize_t raw_read_page(struct mtd_info *mtd, void *dst, loff_t offset)
> @@ -1625,3 +1627,94 @@ int imx7_bbu_nand_register_handler(const char *name, unsigned long flags)
> return ret;
> }
> #endif
> +
> +static void dump_fcb_n(struct fcb_block **fcbs, int n)
> +{
> + int i;
> +
> + if (!n || !fcbs[n])
> + goto skip_compare;
> +
> + for (i = 0; i < n; i++) {
> + if (!fcbs[i] || !fcbs[n])
> + continue;
> +
> + if (!memcmp(fcbs[i], fcbs[n], sizeof(struct fcb_block))) {
> + printf("FCB block#%d: same as FCB block#%d\n", n, i);
> + return;
> + }
> + }
> +
> +skip_compare:
> + if (fcbs[n]) {
> + printf("FCB block#%d:\n", n);
> + dump_fcb(fcbs[n]);
> + } else {
> + printf("FCB block#%d: NULL\n", n);
> + }
> +}
> +
> +#ifdef CONFIG_ARCH_IMX28
Why this #ifdef? Can't we do this by cpu_is_mx28()?
Regards,
Marco
> +static int fcb_read(struct mtd_info *mtd, int block, struct fcb_block **retfcb)
> +{
> + return fcb_read_hamming_13_8(mtd, block, retfcb);
> +}
> +#else
> +static int fcb_read(struct mtd_info *mtd, int block, struct fcb_block **retfcb)
> +{
> + if (cpu_is_mx7())
> + return imx7_fcb_read(mtd, block, retfcb);
> + else if (fcb_is_bch_encoded())
> + return fcb_read_bch(mtd, block, retfcb);
> + else
> + return fcb_read_hamming_13_8(mtd, block, retfcb);
> +}
> +#endif
> +
> +static int cmd_fcb(int argc, char *argv[])
> +{
> + struct cdev *cdev;
> + struct mtd_info *mtd;
> + struct fcb_block *fcb[4] = {};
> + int i, ret;
> +
> + cdev = cdev_open_by_name("nand0", O_RDONLY);
> + if (!cdev) {
> + printf("Cannot open nand0\n");
> + return COMMAND_ERROR;
> + }
> +
> + mtd = cdev->mtd;
> + if (!mtd) {
> + ret = COMMAND_ERROR;
> + goto out;
> + }
> +
> + for (i = 0; i < 4; i++)
> + fcb_read(mtd, i, &fcb[i]);
> +
> + for (i = 0; i < 4; i++)
> + dump_fcb_n(fcb, i);
> +
> + for (i = 0; i < 4; i++)
> + free(fcb[i]);
> +
> + ret = 0;
> +
> +out:
> + cdev_close(cdev);
> +
> + return ret;
> +}
> +
> +BAREBOX_CMD_HELP_START(fcb)
> +BAREBOX_CMD_HELP_TEXT("Dump FCB as found on /dev/nand0")
> +BAREBOX_CMD_HELP_END
> +
> +BAREBOX_CMD_START(fcb)
> + .cmd = cmd_fcb,
> + BAREBOX_CMD_DESC("Dump Flash Control Block (FCB)")
> + BAREBOX_CMD_GROUP(CMD_GRP_MISC)
> + BAREBOX_CMD_HELP(cmd_fcb_help)
> + BAREBOX_CMD_COMPLETE(empty_complete)
> +BAREBOX_CMD_END
> --
> 2.30.2
>
>
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command
2022-11-02 8:44 ` Marco Felsch
@ 2022-11-02 10:55 ` Sascha Hauer
2022-11-02 11:01 ` Marco Felsch
0 siblings, 1 reply; 26+ messages in thread
From: Sascha Hauer @ 2022-11-02 10:55 UTC (permalink / raw)
To: Marco Felsch; +Cc: Barebox List
On Wed, Nov 02, 2022 at 09:44:41AM +0100, Marco Felsch wrote:
> > +static void dump_fcb_n(struct fcb_block **fcbs, int n)
> > +{
> > + int i;
> > +
> > + if (!n || !fcbs[n])
> > + goto skip_compare;
> > +
> > + for (i = 0; i < n; i++) {
> > + if (!fcbs[i] || !fcbs[n])
> > + continue;
> > +
> > + if (!memcmp(fcbs[i], fcbs[n], sizeof(struct fcb_block))) {
> > + printf("FCB block#%d: same as FCB block#%d\n", n, i);
> > + return;
> > + }
> > + }
> > +
> > +skip_compare:
> > + if (fcbs[n]) {
> > + printf("FCB block#%d:\n", n);
> > + dump_fcb(fcbs[n]);
> > + } else {
> > + printf("FCB block#%d: NULL\n", n);
> > + }
> > +}
> > +
> > +#ifdef CONFIG_ARCH_IMX28
>
> Why this #ifdef? Can't we do this by cpu_is_mx28()?
i.MX28 is a different architecture in barebox, it's in
arch/arm/mach-mxs/. We do not have the cpu_is_mx7() and cpu_is_mx6ul()
macros there.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command
2022-11-02 10:55 ` Sascha Hauer
@ 2022-11-02 11:01 ` Marco Felsch
2022-11-02 11:29 ` Sascha Hauer
0 siblings, 1 reply; 26+ messages in thread
From: Marco Felsch @ 2022-11-02 11:01 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
On 22-11-02, Sascha Hauer wrote:
> On Wed, Nov 02, 2022 at 09:44:41AM +0100, Marco Felsch wrote:
> > > +static void dump_fcb_n(struct fcb_block **fcbs, int n)
> > > +{
> > > + int i;
> > > +
> > > + if (!n || !fcbs[n])
> > > + goto skip_compare;
> > > +
> > > + for (i = 0; i < n; i++) {
> > > + if (!fcbs[i] || !fcbs[n])
> > > + continue;
> > > +
> > > + if (!memcmp(fcbs[i], fcbs[n], sizeof(struct fcb_block))) {
> > > + printf("FCB block#%d: same as FCB block#%d\n", n, i);
> > > + return;
> > > + }
> > > + }
> > > +
> > > +skip_compare:
> > > + if (fcbs[n]) {
> > > + printf("FCB block#%d:\n", n);
> > > + dump_fcb(fcbs[n]);
> > > + } else {
> > > + printf("FCB block#%d: NULL\n", n);
> > > + }
> > > +}
> > > +
> > > +#ifdef CONFIG_ARCH_IMX28
> >
> > Why this #ifdef? Can't we do this by cpu_is_mx28()?
>
> i.MX28 is a different architecture in barebox, it's in
> arch/arm/mach-mxs/. We do not have the cpu_is_mx7() and cpu_is_mx6ul()
> macros there.
Argh.. always messing the mxs/mxc stuff up in my head. Got your point,
but shouldn't we add the macros instead of adding the #ifdef here?
Regards,
Marco
>
> Sascha
>
> --
> Pengutronix e.K. | |
> Steuerwalder Str. 21 | http://www.pengutronix.de/ |
> 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH 14/14] imx-bbu-nand-fcb: Add fcb command
2022-11-02 11:01 ` Marco Felsch
@ 2022-11-02 11:29 ` Sascha Hauer
0 siblings, 0 replies; 26+ messages in thread
From: Sascha Hauer @ 2022-11-02 11:29 UTC (permalink / raw)
To: Marco Felsch; +Cc: Barebox List
On Wed, Nov 02, 2022 at 12:01:15PM +0100, Marco Felsch wrote:
> On 22-11-02, Sascha Hauer wrote:
> > On Wed, Nov 02, 2022 at 09:44:41AM +0100, Marco Felsch wrote:
> > > > +static void dump_fcb_n(struct fcb_block **fcbs, int n)
> > > > +{
> > > > + int i;
> > > > +
> > > > + if (!n || !fcbs[n])
> > > > + goto skip_compare;
> > > > +
> > > > + for (i = 0; i < n; i++) {
> > > > + if (!fcbs[i] || !fcbs[n])
> > > > + continue;
> > > > +
> > > > + if (!memcmp(fcbs[i], fcbs[n], sizeof(struct fcb_block))) {
> > > > + printf("FCB block#%d: same as FCB block#%d\n", n, i);
> > > > + return;
> > > > + }
> > > > + }
> > > > +
> > > > +skip_compare:
> > > > + if (fcbs[n]) {
> > > > + printf("FCB block#%d:\n", n);
> > > > + dump_fcb(fcbs[n]);
> > > > + } else {
> > > > + printf("FCB block#%d: NULL\n", n);
> > > > + }
> > > > +}
> > > > +
> > > > +#ifdef CONFIG_ARCH_IMX28
> > >
> > > Why this #ifdef? Can't we do this by cpu_is_mx28()?
> >
> > i.MX28 is a different architecture in barebox, it's in
> > arch/arm/mach-mxs/. We do not have the cpu_is_mx7() and cpu_is_mx6ul()
> > macros there.
>
> Argh.. always messing the mxs/mxc stuff up in my head. Got your point,
> but shouldn't we add the macros instead of adding the #ifdef here?
Right. We have several cpu_is_mx* macros there already, so we can just
add the missing ones and avoid the ifdeffery.
Sascha
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 26+ messages in thread