mtd: rawnand: loongson: Add Loongson-2K nand controller support
Subsystems (5)
v2 cover mtd: rawnand: loongson: Add Loongson-2K nand controller support
Hi all:
This patchset adds support for the Loongson-2K0500/Loongson-2K1000 NAND controllers, which are similar to the Loongson-1C NAND controller.
They support a maximum capacity of 16GB FLASH per chip, with a maximum page size of 8KB. The chip supports up to 4 chip selects and 4 RDY signals.
The key difference between the Loongson-2K NAND controllers is that the Loongson-2K1000 explicitly configures the DMA controller routing, while the Loongson-2K0500 defaults to using APBDMA0.
Summary of the patchset:
Ptach 1-2: Rename all prefixes from ls1x to loongson Patch 3: Add 6-byte NAND ID reading
Patch 4: Add chip select support
Patch 5-6: Add Loongson-2K0500 NAND controller support Patch 7-8: Add Loongson-2K1000 NAND controller support
Thanks.
-------
V2:
Based on linux-mtd/nand/next.
Patch (5/8):
- Add Acked-by tag from Rob, thanks;
Patch (7/8):
- Update reg-names attribute description.
Link to V1:
https://lore.kernel.org/all/[email protected]/
Binbin Zhou (7):
mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson
mtd: rawnand: loongson: Rename loongson1 to loongson
mtd: rawnand: loongson: Add nand chip select support
dt-bindings: mtd: loongson,ls1b-nand-controller: Document the
Loongson-2K0500 NAND controller
mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
dt-bindings: mtd: loongson,ls1b-nand-controller: Document the
Loongson-2K1000 NAND controller
mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support
Keguang Zhang (1):
mtd: rawnand: loongson: Add 6-byte NAND ID reading support
.../mtd/loongson,ls1b-nand-controller.yaml | 56 +- MAINTAINERS | 2 +- drivers/mtd/nand/raw/Kconfig | 8 +- drivers/mtd/nand/raw/Makefile | 2 +- .../mtd/nand/raw/loongson-nand-controller.c | 1032 +++++++++++++++++ .../mtd/nand/raw/loongson1-nand-controller.c | 836 ------------- 6 files changed, 1091 insertions(+), 845 deletions(-) create mode 100644 drivers/mtd/nand/raw/loongson-nand-controller.c delete mode 100644 drivers/mtd/nand/raw/loongson1-nand-controller.c
base-commit: fb2fae70e7e985c4acb1ad96110d8b98bb64a87c
Signature · 1 line
2.47.3
PATCH v2 1/8 mtd: rawnand: loongson1: Rename the prefix from ls1x to loongson
I am going to introduce the NAND controllers of the Loongson-2K series CPUs, which are similar to Loongson-1.
As preparation, first rename all prefixes from ls1x to loongson.
No functional change intended.
--- .../mtd/nand/raw/loongson1-nand-controller.c | 337 +++++++++--------- 1 file changed, 172 insertions(+), 165 deletions(-)
drivers/mtd/nand/raw/loongson1-nand-controller.c +172 -165
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0-or-later /* -* NAND Controller Driver for Loongson-1 SoC +* NAND Controller Driver for Loongson family chips * * Copyright (C) 2015-2025 Keguang Zhang <[email protected]> */
@@ -17,42 +17,45 @@#include <linux/regmap.h> #include <linux/sizes.h> -/* Loongson-1 NAND Controller Registers */ -#define LS1X_NAND_CMD 0x0 -#define LS1X_NAND_ADDR1 0x4 -#define LS1X_NAND_ADDR2 0x8 -#define LS1X_NAND_TIMING 0xc -#define LS1X_NAND_IDL 0x10 -#define LS1X_NAND_IDH_STATUS 0x14 -#define LS1X_NAND_PARAM 0x18 -#define LS1X_NAND_OP_NUM 0x1c - -/* NAND Command Register Bits */ -#define LS1X_NAND_CMD_OP_DONE BIT(10) -#define LS1X_NAND_CMD_OP_SPARE BIT(9) -#define LS1X_NAND_CMD_OP_MAIN BIT(8) -#define LS1X_NAND_CMD_STATUS BIT(7) -#define LS1X_NAND_CMD_RESET BIT(6) -#define LS1X_NAND_CMD_READID BIT(5) -#define LS1X_NAND_CMD_BLOCKS_ERASE BIT(4) -#define LS1X_NAND_CMD_ERASE BIT(3) -#define LS1X_NAND_CMD_WRITE BIT(2) -#define LS1X_NAND_CMD_READ BIT(1) -#define LS1X_NAND_CMD_VALID BIT(0) - -#define LS1X_NAND_WAIT_CYCLE_MASK GENMASK(7, 0) -#define LS1X_NAND_HOLD_CYCLE_MASK GENMASK(15, 8) -#define LS1X_NAND_CELL_SIZE_MASK GENMASK(11, 8) - -#define LS1X_NAND_COL_ADDR_CYC 2U -#define LS1X_NAND_MAX_ADDR_CYC 5U - -#define BITS_PER_WORD (4 * BITS_PER_BYTE) - -struct ls1x_nand_host ; - -struct ls1x_nand_op { -char addrs[LS1X_NAND_MAX_ADDR_CYC ]; +/* Loongson NAND Controller Registers */ +#define LOONGSON_NAND_CMD 0x0 +#define LOONGSON_NAND_ADDR1 0x4 +#define LOONGSON_NAND_ADDR2 0x8 +#define LOONGSON_NAND_TIMING 0xc +#define LOONGSON_NAND_IDL 0x10 +#define LOONGSON_NAND_IDH_STATUS 0x14 +#define LOONGSON_NAND_PARAM 0x18 +#define LOONGSON_NAND_OP_NUM 0x1c + +/* Bitfields of nand command register */ +#define LOONGSON_NAND_CMD_OP_DONE BIT(10) +#define LOONGSON_NAND_CMD_OP_SPARE BIT(9) +#define LOONGSON_NAND_CMD_OP_MAIN BIT(8) +#define LOONGSON_NAND_CMD_STATUS BIT(7) +#define LOONGSON_NAND_CMD_RESET BIT(6) +#define LOONGSON_NAND_CMD_READID BIT(5) +#define LOONGSON_NAND_CMD_BLOCKS_ERASE BIT(4) +#define LOONGSON_NAND_CMD_ERASE BIT(3) +#define LOONGSON_NAND_CMD_WRITE BIT(2) +#define LOONGSON_NAND_CMD_READ BIT(1) +#define LOONGSON_NAND_CMD_VALID BIT(0) + +/* Bitfields of nand timing register */ +#define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0) +#define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8) + +/* Bitfields of nand parameter register */ +#define LOONGSON_NAND_CELL_SIZE_MASK GENMASK(11, 8) + +#define LOONGSON_NAND_COL_ADDR_CYC 2U +#define LOONGSON_NAND_MAX_ADDR_CYC 5U + +#define BITS_PER_WORD (4 * BITS_PER_BYTE) + +struct loongson_nand_host ; + +struct loongson_nand_op { +char addrs[LOONGSON_NAND_MAX_ADDR_CYC ];unsigned int naddrs;unsigned int addrs_offset;unsigned int aligned_offset;
@@ -69,19 +72,19 @@ struct ls1x_nand_op {char *buf; }; -struct ls1x_nand_data { +struct loongson_nand_data {unsigned int status_field;unsigned int op_scope_field;unsigned int hold_cycle;unsigned int wait_cycle; -void (*set_addr)(struct ls1x_nand_host *host,struct ls1x_nand_op *op); +void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); }; -struct ls1x_nand_host { +struct loongson_nand_host {struct device *dev;struct nand_chip chip;struct nand_controller controller; -const struct ls1x_nand_data *data; +const struct loongson_nand_data *data;void __iomem *reg_base;struct regmap *regmap;/* DMA Engine stuff */
@@ -91,40 +94,41 @@ struct ls1x_nand_host {struct completion dma_complete; }; -static const struct regmap_config ls1x_nand_regmap_config = { +static const struct regmap_config loongson_nand_regmap_config = { .reg_bits =32 , .val_bits =32 , .reg_stride =4 , }; -static int ls1x_nand_op_cmd_mapping (struct nand_chip *chip,struct ls1x_nand_op *op,u8 opcode) +static int loongson_nand_op_cmd_mapping (struct nand_chip *chip,struct loongson_nand_op *op, +u8 opcode) { -struct ls1x_nand_host *host =nand_get_controller_data (chip); +struct loongson_nand_host *host =nand_get_controller_data (chip); op->row_start = chip->page_shift +1 ;/* The controller abstracts the following NAND operations. */ switch (opcode) {case NAND_CMD_STATUS : - op->cmd_reg =LS1X_NAND_CMD_STATUS ; + op->cmd_reg =LOONGSON_NAND_CMD_STATUS ;break ;case NAND_CMD_RESET : - op->cmd_reg =LS1X_NAND_CMD_RESET ; + op->cmd_reg =LOONGSON_NAND_CMD_RESET ;break ;case NAND_CMD_READID : op->is_readid = true; - op->cmd_reg =LS1X_NAND_CMD_READID ; + op->cmd_reg =LOONGSON_NAND_CMD_READID ;break ;case NAND_CMD_ERASE1 : op->is_erase = true; - op->addrs_offset =LS1X_NAND_COL_ADDR_CYC ; + op->addrs_offset =LOONGSON_NAND_COL_ADDR_CYC ;break ;case NAND_CMD_ERASE2 :if (!op->is_erase)return -EOPNOTSUPP ;/* During erasing, row_start differs from the default value. */ op->row_start = chip->page_shift; - op->cmd_reg =LS1X_NAND_CMD_ERASE ; + op->cmd_reg =LOONGSON_NAND_CMD_ERASE ;break ;case NAND_CMD_SEQIN : op->is_write = true;
@@ -132,7 +136,7 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_opcase NAND_CMD_PAGEPROG :if (!op->is_write)return -EOPNOTSUPP ; - op->cmd_reg =LS1X_NAND_CMD_WRITE ; + op->cmd_reg =LOONGSON_NAND_CMD_WRITE ;break ;case NAND_CMD_READ0 : op->is_read = true;
@@ -140,7 +144,7 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_opcase NAND_CMD_READSTART :if (!op->is_read)return -EOPNOTSUPP ; - op->cmd_reg =LS1X_NAND_CMD_READ ; + op->cmd_reg =LOONGSON_NAND_CMD_READ ;break ;case NAND_CMD_RNDOUT : op->is_change_column = true;
@@ -148,7 +152,7 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_opcase NAND_CMD_RNDOUTSTART :if (!op->is_change_column)return -EOPNOTSUPP ; - op->cmd_reg =LS1X_NAND_CMD_READ ; + op->cmd_reg =LOONGSON_NAND_CMD_READ ;break ;default :dev_dbg (host->dev,"unsupported opcode: %u\n" , opcode);
@@ -158,8 +162,8 @@ static int ls1x_nand_op_cmd_mapping(struct nand_chip *chip, struct ls1x_nand_opreturn 0 ; } -static int ls1x_nand_parse_instructions (struct nand_chip *chip, -const struct nand_subop *subop,struct ls1x_nand_op *op) +static int loongson_nand_parse_instructions (struct nand_chip *chip,const struct nand_subop *subop, +struct loongson_nand_op *op) {unsigned int op_id;int ret;
@@ -171,14 +175,14 @@ static int ls1x_nand_parse_instructions(struct nand_chip *chip,switch (instr->type) {case NAND_OP_CMD_INSTR : - ret =ls1x_nand_op_cmd_mapping (chip, op, instr->ctx.cmd.opcode); + ret =loongson_nand_op_cmd_mapping (chip, op, instr->ctx.cmd.opcode);if (ret <0 )return ret;break ;case NAND_OP_ADDR_INSTR : naddrs =nand_subop_get_num_addr_cyc (subop, op_id); -if (naddrs >LS1X_NAND_MAX_ADDR_CYC ) +if (naddrs >LOONGSON_NAND_MAX_ADDR_CYC )return -EOPNOTSUPP ; op->naddrs = naddrs; offset =nand_subop_get_addr_start_off (subop, op_id);
@@ -206,57 +210,57 @@ static int ls1x_nand_parse_instructions(struct nand_chip *chip,return 0 ; } -static void ls1b_nand_set_addr (struct ls1x_nand_host *host,struct ls1x_nand_op *op) +static void ls1b_nand_set_addr (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;int i; -for (i =0 ; i <LS1X_NAND_MAX_ADDR_CYC ; i++) { +for (i =0 ; i <LOONGSON_NAND_MAX_ADDR_CYC ; i++) {int shift, mask, val; -if (i <LS1X_NAND_COL_ADDR_CYC ) { +if (i <LOONGSON_NAND_COL_ADDR_CYC ) { shift = i *BITS_PER_BYTE ; mask = (u32 )0xff << shift; mask &=GENMASK (chip->page_shift,0 ); val = (u32 )op->addrs[i] << shift; -regmap_update_bits (host->regmap,LS1X_NAND_ADDR1 , mask, val); +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR1 , mask, val); }else if (!op->is_change_column) { - shift = op->row_start + (i -LS1X_NAND_COL_ADDR_CYC ) *BITS_PER_BYTE ; + shift = op->row_start + (i -LOONGSON_NAND_COL_ADDR_CYC ) *BITS_PER_BYTE ; mask = (u32 )0xff << shift; val = (u32 )op->addrs[i] << shift; -regmap_update_bits (host->regmap,LS1X_NAND_ADDR1 , mask, val); +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR1 , mask, val);if (i ==4 ) { mask = (u32 )0xff >> (BITS_PER_WORD - shift); val = (u32 )op->addrs[i] >> (BITS_PER_WORD - shift); -regmap_update_bits (host->regmap,LS1X_NAND_ADDR2 , mask, val); +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , mask, val); } } } } -static void ls1c_nand_set_addr (struct ls1x_nand_host *host,struct ls1x_nand_op *op) +static void ls1c_nand_set_addr (struct loongson_nand_host *host,struct loongson_nand_op *op) {int i; -for (i =0 ; i <LS1X_NAND_MAX_ADDR_CYC ; i++) { +for (i =0 ; i <LOONGSON_NAND_MAX_ADDR_CYC ; i++) {int shift, mask, val; -if (i <LS1X_NAND_COL_ADDR_CYC ) { +if (i <LOONGSON_NAND_COL_ADDR_CYC ) { shift = i *BITS_PER_BYTE ; mask = (u32 )0xff << shift; val = (u32 )op->addrs[i] << shift; -regmap_update_bits (host->regmap,LS1X_NAND_ADDR1 , mask, val); +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR1 , mask, val); }else if (!op->is_change_column) { - shift = (i -LS1X_NAND_COL_ADDR_CYC ) *BITS_PER_BYTE ; + shift = (i -LOONGSON_NAND_COL_ADDR_CYC ) *BITS_PER_BYTE ; mask = (u32 )0xff << shift; val = (u32 )op->addrs[i] << shift; -regmap_update_bits (host->regmap,LS1X_NAND_ADDR2 , mask, val); +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , mask, val); } } } -static void ls1x_nand_trigger_op (struct ls1x_nand_host *host,struct ls1x_nand_op *op) +static void loongson_nand_trigger_op (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;struct mtd_info *mtd =nand_to_mtd (chip);
@@ -280,7 +284,7 @@ static void ls1x_nand_trigger_op(struct ls1x_nand_host *host, struct ls1x_nand_oelse op->len = op->orig_len; -writel (op->len, host->reg_base +LS1X_NAND_OP_NUM ); +writel (op->len, host->reg_base +LOONGSON_NAND_OP_NUM );/* set operation area and scope */ col = op->addrs[1 ] <<BITS_PER_BYTE | op->addrs[0 ];
@@ -288,33 +292,35 @@ static void ls1x_nand_trigger_op(struct ls1x_nand_host *host, struct ls1x_nand_ounsigned int op_scope =0 ;if (col < mtd->writesize) { - op->cmd_reg |=LS1X_NAND_CMD_OP_MAIN ; + op->cmd_reg |=LOONGSON_NAND_CMD_OP_MAIN ; op_scope = mtd->writesize; } - op->cmd_reg |=LS1X_NAND_CMD_OP_SPARE ; + op->cmd_reg |=LOONGSON_NAND_CMD_OP_SPARE ; op_scope += mtd->oobsize; op_scope <<=__ffs (host->data->op_scope_field); -regmap_update_bits (host->regmap,LS1X_NAND_PARAM , +regmap_update_bits (host->regmap,LOONGSON_NAND_PARAM , host->data->op_scope_field, op_scope); }/* set command */ -writel (op->cmd_reg, host->reg_base +LS1X_NAND_CMD ); +writel (op->cmd_reg, host->reg_base +LOONGSON_NAND_CMD );/* trigger operation */ -regmap_write_bits (host->regmap,LS1X_NAND_CMD ,LS1X_NAND_CMD_VALID ,LS1X_NAND_CMD_VALID ); +regmap_write_bits (host->regmap,LOONGSON_NAND_CMD ,LOONGSON_NAND_CMD_VALID , +LOONGSON_NAND_CMD_VALID ); } -static int ls1x_nand_wait_for_op_done (struct ls1x_nand_host *host,struct ls1x_nand_op *op) +static int loongson_nand_wait_for_op_done (struct loongson_nand_host *host, +struct loongson_nand_op *op) {unsigned int val;int ret =0 ;if (op->rdy_timeout_ms) { - ret =regmap_read_poll_timeout (host->regmap,LS1X_NAND_CMD , - val, val &LS1X_NAND_CMD_OP_DONE , + ret =regmap_read_poll_timeout (host->regmap,LOONGSON_NAND_CMD , + val, val &LOONGSON_NAND_CMD_OP_DONE ,0 , op->rdy_timeout_ms *MSEC_PER_SEC );if (ret)dev_err (host->dev,"operation failed\n" );
@@ -323,9 +329,9 @@ static int ls1x_nand_wait_for_op_done(struct ls1x_nand_host *host, struct ls1x_nreturn ret; } -static void ls1x_nand_dma_callback (void *data) +static void loongson_nand_dma_callback (void *data) { -struct ls1x_nand_host *host = (struct ls1x_nand_host *)data; +struct loongson_nand_host *host = (struct loongson_nand_host *)data;struct dma_chan *chan = host->dma_chan;struct device *dev = chan->device->dev;enum dma_status status;
@@ -339,7 +345,7 @@ static void ls1x_nand_dma_callback(void *data) } } -static int ls1x_nand_dma_transfer (struct ls1x_nand_host *host,struct ls1x_nand_op *op) +static int loongson_nand_dma_transfer (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;struct dma_chan *chan = host->dma_chan;
@@ -374,7 +380,7 @@ static int ls1x_nand_dma_transfer(struct ls1x_nand_host *host, struct ls1x_nand_ ret = -ENOMEM ; goto err; } - desc->callback = ls1x_nand_dma_callback; + desc->callback = loongson_nand_dma_callback; desc->callback_param = host; host->dma_cookie =dmaengine_submit (desc);
@@ -405,51 +411,51 @@ static int ls1x_nand_dma_transfer(struct ls1x_nand_host *host, struct ls1x_nand_return ret; } -static int ls1x_nand_data_type_exec (struct nand_chip *chip,const struct nand_subop *subop) +static int loongson_nand_data_type_exec (struct nand_chip *chip,const struct nand_subop *subop) { -struct ls1x_nand_host *host =nand_get_controller_data (chip); -struct ls1x_nand_op op = {}; +struct loongson_nand_host *host =nand_get_controller_data (chip); +struct loongson_nand_op op = {};int ret; - ret =ls1x_nand_parse_instructions (chip, subop, &op); + ret =loongson_nand_parse_instructions (chip, subop, &op);if (ret)return ret; -ls1x_nand_trigger_op (host, &op); +loongson_nand_trigger_op (host, &op); - ret =ls1x_nand_dma_transfer (host, &op); + ret =loongson_nand_dma_transfer (host, &op);if (ret)return ret; -return ls1x_nand_wait_for_op_done (host, &op); +return loongson_nand_wait_for_op_done (host, &op); } -static int ls1x_nand_misc_type_exec (struct nand_chip *chip, -const struct nand_subop *subop,struct ls1x_nand_op *op) +static int loongson_nand_misc_type_exec (struct nand_chip *chip,const struct nand_subop *subop, +struct loongson_nand_op *op) { -struct ls1x_nand_host *host =nand_get_controller_data (chip); +struct loongson_nand_host *host =nand_get_controller_data (chip);int ret; - ret =ls1x_nand_parse_instructions (chip, subop, op); + ret =loongson_nand_parse_instructions (chip, subop, op);if (ret)return ret; -ls1x_nand_trigger_op (host, op); +loongson_nand_trigger_op (host, op); -return ls1x_nand_wait_for_op_done (host, op); +return loongson_nand_wait_for_op_done (host, op); } -static int ls1x_nand_zerolen_type_exec (struct nand_chip *chip,const struct nand_subop *subop) +static int loongson_nand_zerolen_type_exec (struct nand_chip *chip,const struct nand_subop *subop) { -struct ls1x_nand_op op = {}; +struct loongson_nand_op op = {}; -return ls1x_nand_misc_type_exec (chip, subop, &op); +return loongson_nand_misc_type_exec (chip, subop, &op); } -static int ls1x_nand_read_id_type_exec (struct nand_chip *chip,const struct nand_subop *subop) +static int loongson_nand_read_id_type_exec (struct nand_chip *chip,const struct nand_subop *subop) { -struct ls1x_nand_host *host =nand_get_controller_data (chip); -struct ls1x_nand_op op = {}; +struct loongson_nand_host *host =nand_get_controller_data (chip); +struct loongson_nand_op op = {};int i, ret;union {char ids[5 ];
@@ -459,12 +465,12 @@ static int ls1x_nand_read_id_type_exec(struct nand_chip *chip, const struct nand }; } nand_id; - ret =ls1x_nand_misc_type_exec (chip, subop, &op); + ret =loongson_nand_misc_type_exec (chip, subop, &op);if (ret)return ret; - nand_id.idl =readl (host->reg_base +LS1X_NAND_IDL ); - nand_id.idh =readb (host->reg_base +LS1X_NAND_IDH_STATUS ); + nand_id.idl =readl (host->reg_base +LOONGSON_NAND_IDL ); + nand_id.idh =readb (host->reg_base +LOONGSON_NAND_IDH_STATUS );for (i =0 ; i <min (sizeof (nand_id.ids), op.orig_len); i++) op.buf[i] = nand_id.ids[sizeof (nand_id.ids) -1 - i];
@@ -472,60 +478,61 @@ static int ls1x_nand_read_id_type_exec(struct nand_chip *chip, const struct nandreturn ret; } -static int ls1x_nand_read_status_type_exec (struct nand_chip *chip,const struct nand_subop *subop) +static int loongson_nand_read_status_type_exec (struct nand_chip *chip, +const struct nand_subop *subop) { -struct ls1x_nand_host *host =nand_get_controller_data (chip); -struct ls1x_nand_op op = {}; +struct loongson_nand_host *host =nand_get_controller_data (chip); +struct loongson_nand_op op = {};int val, ret; - ret =ls1x_nand_misc_type_exec (chip, subop, &op); + ret =loongson_nand_misc_type_exec (chip, subop, &op);if (ret)return ret; - val =readl (host->reg_base +LS1X_NAND_IDH_STATUS ); + val =readl (host->reg_base +LOONGSON_NAND_IDH_STATUS ); val &= ~host->data->status_field; op.buf[0 ] = val <<ffs (host->data->status_field);return ret; } -static const struct nand_op_parser ls1x_nand_op_parser =NAND_OP_PARSER ( +static const struct nand_op_parser loongson_nand_op_parser =NAND_OP_PARSER (NAND_OP_PARSER_PATTERN ( - ls1x_nand_read_id_type_exec, + loongson_nand_read_id_type_exec,NAND_OP_PARSER_PAT_CMD_ELEM (false), -NAND_OP_PARSER_PAT_ADDR_ELEM (false,LS1X_NAND_MAX_ADDR_CYC ), +NAND_OP_PARSER_PAT_ADDR_ELEM (false,LOONGSON_NAND_MAX_ADDR_CYC ),NAND_OP_PARSER_PAT_DATA_IN_ELEM (false,8 )),NAND_OP_PARSER_PATTERN ( - ls1x_nand_read_status_type_exec, + loongson_nand_read_status_type_exec,NAND_OP_PARSER_PAT_CMD_ELEM (false),NAND_OP_PARSER_PAT_DATA_IN_ELEM (false,1 )),NAND_OP_PARSER_PATTERN ( - ls1x_nand_zerolen_type_exec, + loongson_nand_zerolen_type_exec,NAND_OP_PARSER_PAT_CMD_ELEM (false),NAND_OP_PARSER_PAT_WAITRDY_ELEM (false)),NAND_OP_PARSER_PATTERN ( - ls1x_nand_zerolen_type_exec, + loongson_nand_zerolen_type_exec,NAND_OP_PARSER_PAT_CMD_ELEM (false), -NAND_OP_PARSER_PAT_ADDR_ELEM (false,LS1X_NAND_MAX_ADDR_CYC ), +NAND_OP_PARSER_PAT_ADDR_ELEM (false,LOONGSON_NAND_MAX_ADDR_CYC ),NAND_OP_PARSER_PAT_CMD_ELEM (false),NAND_OP_PARSER_PAT_WAITRDY_ELEM (false)),NAND_OP_PARSER_PATTERN ( - ls1x_nand_data_type_exec, + loongson_nand_data_type_exec,NAND_OP_PARSER_PAT_CMD_ELEM (false), -NAND_OP_PARSER_PAT_ADDR_ELEM (false,LS1X_NAND_MAX_ADDR_CYC ), +NAND_OP_PARSER_PAT_ADDR_ELEM (false,LOONGSON_NAND_MAX_ADDR_CYC ),NAND_OP_PARSER_PAT_CMD_ELEM (false),NAND_OP_PARSER_PAT_WAITRDY_ELEM (true),NAND_OP_PARSER_PAT_DATA_IN_ELEM (false,0 )),NAND_OP_PARSER_PATTERN ( - ls1x_nand_data_type_exec, + loongson_nand_data_type_exec,NAND_OP_PARSER_PAT_CMD_ELEM (false), -NAND_OP_PARSER_PAT_ADDR_ELEM (false,LS1X_NAND_MAX_ADDR_CYC ), +NAND_OP_PARSER_PAT_ADDR_ELEM (false,LOONGSON_NAND_MAX_ADDR_CYC ),NAND_OP_PARSER_PAT_DATA_OUT_ELEM (false,0 ),NAND_OP_PARSER_PAT_CMD_ELEM (false), NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)), ); -static int ls1x_nand_is_valid_cmd (u8 opcode) +static int loongson_nand_is_valid_cmd (u8 opcode) {if (opcode ==NAND_CMD_STATUS || opcode ==NAND_CMD_RESET || opcode ==NAND_CMD_READID )return 0 ;
@@ -533,7 +540,7 @@ static int ls1x_nand_is_valid_cmd(u8 opcode)return -EOPNOTSUPP ; } -static int ls1x_nand_is_valid_cmd_seq (u8 opcode1,u8 opcode2) +static int loongson_nand_is_valid_cmd_seq (u8 opcode1,u8 opcode2) {if (opcode1 ==NAND_CMD_RNDOUT && opcode2 ==NAND_CMD_RNDOUTSTART )return 0 ;
@@ -550,7 +557,7 @@ static int ls1x_nand_is_valid_cmd_seq(u8 opcode1, u8 opcode2)return -EOPNOTSUPP ; } -static int ls1x_nand_check_op (struct nand_chip *chip,const struct nand_operation *op) +static int loongson_nand_check_op (struct nand_chip *chip,const struct nand_operation *op) {const struct nand_op_instr *instr1 =NULL , *instr2 =NULL ;int op_id;
@@ -572,23 +579,23 @@ static int ls1x_nand_check_op(struct nand_chip *chip, const struct nand_operatioreturn -EOPNOTSUPP ;if (!instr2) -return ls1x_nand_is_valid_cmd (instr1->ctx.cmd.opcode); +return loongson_nand_is_valid_cmd (instr1->ctx.cmd.opcode); -return ls1x_nand_is_valid_cmd_seq (instr1->ctx.cmd.opcode, instr2->ctx.cmd.opcode); +return loongson_nand_is_valid_cmd_seq (instr1->ctx.cmd.opcode, instr2->ctx.cmd.opcode); } -static int ls1x_nand_exec_op (struct nand_chip *chip, -const struct nand_operation *op,bool check_only) +static int loongson_nand_exec_op (struct nand_chip *chip,const struct nand_operation *op, +bool check_only) {if (check_only) -return ls1x_nand_check_op (chip, op); +return loongson_nand_check_op (chip, op); -return nand_op_parser_exec_op (chip, &ls1x_nand_op_parser, op, check_only); +return nand_op_parser_exec_op (chip, &loongson_nand_op_parser, op, check_only); } -static int ls1x_nand_attach_chip (struct nand_chip *chip) +static int loongson_nand_attach_chip (struct nand_chip *chip) { -struct ls1x_nand_host *host =nand_get_controller_data (chip); +struct loongson_nand_host *host =nand_get_controller_data (chip);u64 chipsize =nanddev_target_size (&chip->base);int cell_size =0 ;
@@ -632,14 +639,14 @@ static int ls1x_nand_attach_chip(struct nand_chip *chip) }/* set cell size */ -regmap_update_bits (host->regmap,LS1X_NAND_PARAM ,LS1X_NAND_CELL_SIZE_MASK , -FIELD_PREP (LS1X_NAND_CELL_SIZE_MASK , cell_size)); +regmap_update_bits (host->regmap,LOONGSON_NAND_PARAM ,LOONGSON_NAND_CELL_SIZE_MASK , +FIELD_PREP (LOONGSON_NAND_CELL_SIZE_MASK , cell_size)); -regmap_update_bits (host->regmap,LS1X_NAND_TIMING ,LS1X_NAND_HOLD_CYCLE_MASK , -FIELD_PREP (LS1X_NAND_HOLD_CYCLE_MASK , host->data->hold_cycle)); +regmap_update_bits (host->regmap,LOONGSON_NAND_TIMING ,LOONGSON_NAND_HOLD_CYCLE_MASK , +FIELD_PREP (LOONGSON_NAND_HOLD_CYCLE_MASK , host->data->hold_cycle)); -regmap_update_bits (host->regmap,LS1X_NAND_TIMING ,LS1X_NAND_WAIT_CYCLE_MASK , -FIELD_PREP (LS1X_NAND_WAIT_CYCLE_MASK , host->data->wait_cycle)); +regmap_update_bits (host->regmap,LOONGSON_NAND_TIMING ,LOONGSON_NAND_WAIT_CYCLE_MASK , +FIELD_PREP (LOONGSON_NAND_WAIT_CYCLE_MASK , host->data->wait_cycle)); chip->ecc.read_page_raw = nand_monolithic_read_page_raw; chip->ecc.write_page_raw = nand_monolithic_write_page_raw;
@@ -647,25 +654,25 @@ static int ls1x_nand_attach_chip(struct nand_chip *chip)return 0 ; } -static const struct nand_controller_ops ls1x_nand_controller_ops = { - .exec_op = ls1x_nand_exec_op, - .attach_chip = ls1x_nand_attach_chip, +static const struct nand_controller_ops loongson_nand_controller_ops = { + .exec_op = loongson_nand_exec_op, + .attach_chip = loongson_nand_attach_chip, }; -static void ls1x_nand_controller_cleanup (struct ls1x_nand_host *host) +static void loongson_nand_controller_cleanup (struct loongson_nand_host *host) {if (host->dma_chan)dma_release_channel (host->dma_chan); } -static int ls1x_nand_controller_init (struct ls1x_nand_host *host) +static int loongson_nand_controller_init (struct loongson_nand_host *host) {struct device *dev = host->dev;struct dma_chan *chan;struct dma_slave_config cfg = {};int ret; - host->regmap =devm_regmap_init_mmio (dev, host->reg_base, &ls1x_nand_regmap_config); + host->regmap =devm_regmap_init_mmio (dev, host->reg_base, &loongson_nand_regmap_config);if (IS_ERR (host->regmap))return dev_err_probe (dev,PTR_ERR (host->regmap),"failed to init regmap\n" );
@@ -687,7 +694,7 @@ static int ls1x_nand_controller_init(struct ls1x_nand_host *host)return 0 ; } -static int ls1x_nand_chip_init (struct ls1x_nand_host *host) +static int loongson_nand_chip_init (struct loongson_nand_host *host) {struct device *dev = host->dev;int nchips =of_get_child_count (dev->of_node);
@@ -728,11 +735,11 @@ static int ls1x_nand_chip_init(struct ls1x_nand_host *host)return 0 ; } -static int ls1x_nand_probe (struct platform_device *pdev) +static int loongson_nand_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev; -const struct ls1x_nand_data *data; -struct ls1x_nand_host *host; +const struct loongson_nand_data *data; +struct loongson_nand_host *host;struct resource *res;int ret;
@@ -759,15 +766,15 @@ static int ls1x_nand_probe(struct platform_device *pdev) host->dev = dev; host->data = data; - host->controller.ops = &ls1x_nand_controller_ops; + host->controller.ops = &loongson_nand_controller_ops;nand_controller_init (&host->controller); - ret =ls1x_nand_controller_init (host); + ret =loongson_nand_controller_init (host);if (ret) goto err; - ret =ls1x_nand_chip_init (host); + ret =loongson_nand_chip_init (host);if (ret) goto err;
@@ -775,31 +782,31 @@ static int ls1x_nand_probe(struct platform_device *pdev)return 0 ; err: -ls1x_nand_controller_cleanup (host); +loongson_nand_controller_cleanup (host);return ret; } -static void ls1x_nand_remove (struct platform_device *pdev) +static void loongson_nand_remove (struct platform_device *pdev) { -struct ls1x_nand_host *host =platform_get_drvdata (pdev); +struct loongson_nand_host *host =platform_get_drvdata (pdev);struct nand_chip *chip = &host->chip;int ret; ret =mtd_device_unregister (nand_to_mtd (chip));WARN_ON (ret);nand_cleanup (chip); -ls1x_nand_controller_cleanup (host); +loongson_nand_controller_cleanup (host); } -static const struct ls1x_nand_data ls1b_nand_data = { +static const struct loongson_nand_data ls1b_nand_data = { .status_field =GENMASK (15 ,8 ), .hold_cycle =0x2 , .wait_cycle =0xc , .set_addr = ls1b_nand_set_addr, }; -static const struct ls1x_nand_data ls1c_nand_data = { +static const struct loongson_nand_data ls1c_nand_data = { .status_field =GENMASK (23 ,16 ), .op_scope_field =GENMASK (29 ,16 ), .hold_cycle =0x2 ,
@@ -807,7 +814,7 @@ static const struct ls1x_nand_data ls1c_nand_data = { .set_addr = ls1c_nand_set_addr, }; -static const struct of_device_id ls1x_nand_match[] = { +static const struct of_device_id loongson_nand_match[] = { { .compatible ="loongson,ls1b-nand-controller" , .data = &ls1b_nand_data,
@@ -818,19 +825,19 @@ static const struct of_device_id ls1x_nand_match[] = { }, {/* sentinel */ } }; -MODULE_DEVICE_TABLE (of, ls1x_nand_match); +MODULE_DEVICE_TABLE (of, loongson_nand_match); -static struct platform_driver ls1x_nand_driver = { - .probe = ls1x_nand_probe, - .remove = ls1x_nand_remove, +static struct platform_driver loongson_nand_driver = { + .probe = loongson_nand_probe, + .remove = loongson_nand_remove, .driver = { .name =KBUILD_MODNAME , - .of_match_table = ls1x_nand_match, + .of_match_table = loongson_nand_match, }, }; -module_platform_driver (ls1x_nand_driver); +module_platform_driver (loongson_nand_driver);MODULE_AUTHOR ("Keguang Zhang <[email protected]>" ); -MODULE_DESCRIPTION ("Loongson-1 NAND Controller Driver" ); +MODULE_DESCRIPTION ("Loongson NAND Controller Driver" );MODULE_LICENSE ("GPL" );
Signature · 1 line
2.47.3
PATCH v2 2/8 mtd: rawnand: loongson: Rename loongson1 to loongson
In reply to Binbin ZhouThe second step in preparing to add Loongson-2K support is to change the names of the driver files and Kconfig options from Loongson1-specific to Loongson-generic.
---
MAINTAINERS | 2 +-
drivers/mtd/nand/raw/Kconfig | 6 +++---
drivers/mtd/nand/raw/Makefile | 2 +-
...ongson1-nand-controller.c => loongson-nand-controller.c} | 0
4 files changed, 5 insertions(+), 5 deletions(-)
rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)MAINTAINERS +1 -1
@@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml F: arch/mips/include/asm/mach-loongson32/ F: arch/mips/loongson32/ F: drivers/*/*loongson1* -F: drivers/mtd/nand/raw/loongson1-nand-controller.c +F: drivers/mtd/nand/raw/loongson-nand-controller.c F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c F: sound/soc/loongson/loongson1_ac97.c
drivers/mtd/nand/raw/Kconfig +3 -3
@@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35 Enables support for the NAND controller found on the Nuvoton MA35 series SoCs. -config MTD_NAND_LOONGSON1 - tristate "Loongson1 NAND controller" +config MTD_NAND_LOONGSON + tristate "Loongson NAND controller" depends on LOONGSON1_APB_DMA || COMPILE_TEST select REGMAP_MMIO help - Enables support for NAND controller on Loongson1 SoCs. + Enables support for NAND controller on Loongson family chips. comment "Misc"
drivers/mtd/nand/raw/Makefile +1 -1
@@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.o
drivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0 -0
Signature · 1 line
2.47.3
Huacai Chen
maintainerRe: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
Hi, Binbin,
Quoted 4 lines · Binbin Zhou
The second step in preparing to add Loongson-2K support is to change the names of the driver files and
Kconfigoptions from Loongson1-specific to Loongson-generic.
Is it possible to merge the first two patches? If not, it is better to use loongson1 rather than loongson in the subject line of this patch.
Huacai
Quoted 64 lines
Signed-off-by Binbin Zhou <[email protected]>--- MAINTAINERS | 2 +- drivers/mtd/nand/raw/Kconfig | 6 +++--- drivers/mtd/nand/raw/Makefile | 2 +- ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)MAINTAINERS +1
-1@@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml F: arch/mips/include/asm/mach-loongson32/ F: arch/mips/loongson32/ F: drivers/*/*loongson1* -F: drivers/mtd/nand/raw/loongson1-nand-controller.c +F: drivers/mtd/nand/raw/loongson-nand-controller.c F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c F: sound/soc/loongson/loongson1_ac97.cdrivers/mtd/nand/raw/Kconfig +3
-3@@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35 Enables support for the NAND controller found on the Nuvoton MA35 series SoCs. -config MTD_NAND_LOONGSON1 - tristate "Loongson1 NAND controller" +config MTD_NAND_LOONGSON + tristate "Loongson NAND controller" depends on LOONGSON1_APB_DMA || COMPILE_TEST select REGMAP_MMIO help - Enables support for NAND controller on Loongson1 SoCs. + Enables support for NAND controller on Loongson family chips. comment "Misc"drivers/mtd/nand/raw/Makefile +1
-1@@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.odrivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0
-1--2.47.3
Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
Hi Huacai:
Thanks for your reply.
Quoted 10 lines · Huacai Chen
Hi, Binbin,
Quoted 4 lines · Binbin Zhou
The second step in preparing to add Loongson-2K support is to change the names of the driver files and
Kconfigoptions from Loongson1-specific to Loongson-generic.Is it possible to merge the first two patches? If not, it is better to use loongson1 rather than loongson in the subject line of this patch.
At first, I thought that separating the renaming of file prefixes from the renaming of file names would make the changes clearer. Another point is whether renaming Kconfig items would be considered API breaking, even though no one is currently referencing them?
Of course, if anyone thinks that separating them is unnecessary, I will merge them in the next version.
Quoted 57 lines
Huacai
Quoted 54 lines
Signed-off-by Binbin Zhou <[email protected]>--- MAINTAINERS | 2 +- drivers/mtd/nand/raw/Kconfig | 6 +++--- drivers/mtd/nand/raw/Makefile | 2 +- ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)MAINTAINERS +1
-1@@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml F: arch/mips/include/asm/mach-loongson32/ F: arch/mips/loongson32/ F: drivers/*/*loongson1* -F: drivers/mtd/nand/raw/loongson1-nand-controller.c +F: drivers/mtd/nand/raw/loongson-nand-controller.c F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c F: sound/soc/loongson/loongson1_ac97.cdrivers/mtd/nand/raw/Kconfig +3
-3@@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35 Enables support for the NAND controller found on the Nuvoton MA35 series SoCs. -config MTD_NAND_LOONGSON1 - tristate "Loongson1 NAND controller" +config MTD_NAND_LOONGSON + tristate "Loongson NAND controller" depends on LOONGSON1_APB_DMA || COMPILE_TEST select REGMAP_MMIO help - Enables support for NAND controller on Loongson1 SoCs. + Enables support for NAND controller on Loongson family chips. comment "Misc"drivers/mtd/nand/raw/Makefile +1
-1@@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o
Quoted 10 lines
Quoted 10 lines
drivers/mtd/nand/raw/Makefile +0
-0nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.odrivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0
-1--2.47.3
--
Thanks.
Binbin
Keguang Zhang
maintainerRe: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
Quoted 17 lines · Binbin Zhou
Hi Huacai:
Thanks for your reply.
Quoted 10 lines · Huacai Chen
Hi, Binbin,
Quoted 4 lines · Binbin Zhou
The second step in preparing to add Loongson-2K support is to change the names of the driver files and
Kconfigoptions from Loongson1-specific to Loongson-generic.Is it possible to merge the first two patches? If not, it is better to use loongson1 rather than loongson in the subject line of this patch.
Quoted 7 lines
At first, I thought that separating the renaming of file prefixes from the renaming of file names would make the changes clearer. Another point is whether renaming
Kconfigitems would be considered API breaking, even though no one is currently referencing them?Of course, if anyone thinks that separating them is unnecessary, I will merge them in the next version.
It’s reasonable to merge the first two patches.
I agree.
Quoted 57 lines
Quoted 57 lines
Huacai
Quoted 54 lines
Signed-off-by Binbin Zhou <[email protected]>--- MAINTAINERS | 2 +- drivers/mtd/nand/raw/Kconfig | 6 +++--- drivers/mtd/nand/raw/Makefile | 2 +- ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)MAINTAINERS +1
-1@@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml F: arch/mips/include/asm/mach-loongson32/ F: arch/mips/loongson32/ F: drivers/*/*loongson1* -F: drivers/mtd/nand/raw/loongson1-nand-controller.c +F: drivers/mtd/nand/raw/loongson-nand-controller.c F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c F: sound/soc/loongson/loongson1_ac97.cdrivers/mtd/nand/raw/Kconfig +3
-3@@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35 Enables support for the NAND controller found on the Nuvoton MA35 series SoCs. -config MTD_NAND_LOONGSON1 - tristate "Loongson1 NAND controller" +config MTD_NAND_LOONGSON + tristate "Loongson NAND controller" depends on LOONGSON1_APB_DMA || COMPILE_TEST select REGMAP_MMIO help - Enables support for NAND controller on Loongson1 SoCs. + Enables support for NAND controller on Loongson family chips. comment "Misc"drivers/mtd/nand/raw/Makefile +1
-1@@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.o
Quoted 14 lines
Quoted 10 lines
Quoted 10 lines
drivers/mtd/nand/raw/Makefile +0
-0nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.odrivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0
-1--2.47.3
--
Thanks.
Binbin
--
Best regards,
Keguang Zhang
Re: [PATCH v2 2/8] mtd: rawnand: loongson: Rename loongson1 to loongson
Hi Keguang:
Thanks for your reply.
Quoted 24 lines · Keguang Zhang
Quoted 22 lines · Binbin Zhou
Hi Huacai:
Thanks for your reply.
Quoted 10 lines · Huacai Chen
Hi, Binbin,
Quoted 4 lines · Binbin Zhou
The second step in preparing to add Loongson-2K support is to change the names of the driver files and
Kconfigoptions from Loongson1-specific to Loongson-generic.Is it possible to merge the first two patches? If not, it is better to use loongson1 rather than loongson in the subject line of this patch.
At first, I thought that separating the renaming of file prefixes from the renaming of file names would make the changes clearer. Another point is whether renaming
Kconfigitems would be considered API breaking, even though no one is currently referencing them?
Quoted 5 lines
Quoted 2 lines
Of course, if anyone thinks that separating them is unnecessary, I will merge them in the next version.
It’s reasonable to merge the first two patches.
I agree.
OK. I will do it in the next version.
Quoted 79 lines
Quoted 58 lines
Quoted 58 lines
Huacai
Quoted 54 lines
Signed-off-by Binbin Zhou <[email protected]>--- MAINTAINERS | 2 +- drivers/mtd/nand/raw/Kconfig | 6 +++--- drivers/mtd/nand/raw/Makefile | 2 +- ...ongson1-nand-controller.c => loongson-nand-controller.c} | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename drivers/mtd/nand/raw/{loongson1-nand-controller.c => loongson-nand-controller.c} (100%)MAINTAINERS +1
-1@@ -16722,7 +16722,7 @@ F: Documentation/devicetree/bindings/*/loongson,ls1*.yaml F: arch/mips/include/asm/mach-loongson32/ F: arch/mips/loongson32/ F: drivers/*/*loongson1* -F: drivers/mtd/nand/raw/loongson1-nand-controller.c +F: drivers/mtd/nand/raw/loongson-nand-controller.c F: drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c F: sound/soc/loongson/loongson1_ac97.cdrivers/mtd/nand/raw/Kconfig +3
-3@@ -462,12 +462,12 @@ config MTD_NAND_NUVOTON_MA35 Enables support for the NAND controller found on the Nuvoton MA35 series SoCs. -config MTD_NAND_LOONGSON1 - tristate "Loongson1 NAND controller" +config MTD_NAND_LOONGSON + tristate "Loongson NAND controller" depends on LOONGSON1_APB_DMA || COMPILE_TEST select REGMAP_MMIO help - Enables support for NAND controller on Loongson1 SoCs. + Enables support for NAND controller on Loongson family chips. comment "Misc"drivers/mtd/nand/raw/Makefile +1
-1@@ -59,7 +59,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton-ma35d1-nand-controller.o -obj-$(CONFIG_MTD_NAND_LOONGSON1) += loongson1-nand-controller.o +obj-$(CONFIG_MTD_NAND_LOONGSON) += loongson-nand-controller.oQuoted 14 lines
Quoted 10 lines
Quoted 10 lines
drivers/mtd/nand/raw/Makefile +0
-0nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.odrivers/mtd/nand/raw/loongson-nand-controller.c renamed from drivers/mtd/nand/raw/loongson1-nand-controller.c +0
-1--2.47.3
--
Thanks.
Binbin--
Best regards,Keguang Zhang
Signature · 2 lines
Thanks. Binbin
PATCH v2 3/8 mtd: rawnand: loongson: Add 6-byte NAND ID reading support
In reply to Binbin ZhouFrom: Keguang Zhang <[email protected]>
Loongson-1C and Loongson-2K SoCs support NAND flash chips with 6-byte ID. However, the current implementation only handles 5-byte ID which can lead to incorrect chip detection.
Extend loongson_nand_read_id_type_exec() to support 6-byte NAND ID.
--- .../mtd/nand/raw/loongson-nand-controller.c | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +23 -6
@@ -50,6 +50,9 @@#define LOONGSON_NAND_COL_ADDR_CYC 2U#define LOONGSON_NAND_MAX_ADDR_CYC 5U +#define LOONGSON_NAND_READ_ID_SLEEP_US 1000 +#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000 +#define BITS_PER_WORD (4 * BITS_PER_BYTE)struct loongson_nand_host ;
@@ -73,6 +76,8 @@ struct loongson_nand_op { };struct loongson_nand_data { +unsigned int max_id_cycle; +unsigned int id_cycle_field;unsigned int status_field;unsigned int op_scope_field;unsigned int hold_cycle;
@@ -458,10 +463,10 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const structstruct loongson_nand_op op = {};int i, ret;union { -char ids[5 ]; +char ids[6 ];struct {int idl; -char idh; +u16 idh; }; } nand_id;
@@ -469,11 +474,16 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const structif (ret)return ret; - nand_id.idl =readl (host->reg_base +LOONGSON_NAND_IDL ); - nand_id.idh =readb (host->reg_base +LOONGSON_NAND_IDH_STATUS ); + ret =regmap_read_poll_timeout (host->regmap,LOONGSON_NAND_IDL , nand_id.idl, nand_id.idl, +LOONGSON_NAND_READ_ID_SLEEP_US , +LOONGSON_NAND_READ_ID_TIMEOUT_US ); +if (ret) +return ret; -for (i =0 ; i <min (sizeof (nand_id.ids), op.orig_len); i++) - op.buf[i] = nand_id.ids[sizeof (nand_id.ids) -1 - i]; + nand_id.idh =readw (host->reg_base +LOONGSON_NAND_IDH_STATUS ); + +for (i =0 ; i <min (host->data->max_id_cycle, op.orig_len); i++) + op.buf[i] = nand_id.ids[host->data->max_id_cycle -1 - i];return ret; }
@@ -676,6 +686,10 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)if (IS_ERR (host->regmap))return dev_err_probe (dev,PTR_ERR (host->regmap),"failed to init regmap\n" ); +if (host->data->id_cycle_field) +regmap_update_bits (host->regmap,LOONGSON_NAND_PARAM , host->data->id_cycle_field, + host->data->max_id_cycle <<__ffs (host->data->id_cycle_field)); + chan =dma_request_chan (dev,"rxtx" );if (IS_ERR (chan))return dev_err_probe (dev,PTR_ERR (chan),"failed to request DMA channel\n" );
@@ -800,6 +814,7 @@ static void loongson_nand_remove(struct platform_device *pdev) }static const struct loongson_nand_data ls1b_nand_data = { + .max_id_cycle =5 , .status_field =GENMASK (15 ,8 ), .hold_cycle =0x2 , .wait_cycle =0xc ,
@@ -807,6 +822,8 @@ static const struct loongson_nand_data ls1b_nand_data = { };static const struct loongson_nand_data ls1c_nand_data = { + .max_id_cycle =6 , + .id_cycle_field =GENMASK (14 ,12 ), .status_field =GENMASK (23 ,16 ), .op_scope_field =GENMASK (29 ,16 ), .hold_cycle =0x2 ,
Signature · 1 line
2.47.3
Huacai Chen
maintainerRe: [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support
Hi, Binbin,
Quoted 52 lines · Binbin Zhou
From: Keguang Zhang <[email protected]>
Loongson-1C and Loongson-2K SoCs support NAND flash chips with 6-byte ID. However, the current implementation only handles 5-byte ID which can lead to incorrect chip detection.
Extend
loongson_nand_read_id_type_exec()to support 6-byte NAND ID.Signed-off-by Keguang Zhang <[email protected]>Signed-off-by Binbin Zhou <[email protected]>--- .../mtd/nand/raw/loongson-nand-controller.c | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-)drivers/mtd/nand/raw/loongson-nand-controller.c +7
-2@@ -50,6 +50,9 @@#define LOONGSON_NAND_COL_ADDR_CYC 2U#define LOONGSON_NAND_MAX_ADDR_CYC 5U +#define LOONGSON_NAND_READ_ID_SLEEP_US 1000 +#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000 +#define BITS_PER_WORD (4 * BITS_PER_BYTE)struct loongson_nand_host ;@@ -73,6 +76,8 @@ struct loongson_nand_op { };struct loongson_nand_data { +unsigned int max_id_cycle; +unsigned int id_cycle_field;unsigned int status_field;unsigned int op_scope_field;unsigned int hold_cycle;@@ -458,10 +463,10 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const structstruct loongson_nand_op op = {};int i, ret;union { -char ids[5 ]; +char ids[6 ];struct {int idl; -char idh; +u16 idh; }; } nand_id;
drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct · line 479
Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3
-2@@ -469,11 +474,16 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const structif (ret)return ret; - nand_id.idl =readl (host->reg_base +LOONGSON_NAND_IDL ); - nand_id.idh =readb (host->reg_base +LOONGSON_NAND_IDH_STATUS ); + ret =regmap_read_poll_timeout (host->regmap,LOONGSON_NAND_IDL , nand_id.idl, nand_id.idl, +LOONGSON_NAND_READ_ID_SLEEP_US , +LOONGSON_NAND_READ_ID_TIMEOUT_US );
The last two lines can be merged.
Huacai
Quoted 43 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +13
-3+if (ret) +return ret; -for (i =0 ; i <min (sizeof (nand_id.ids), op.orig_len); i++) - op.buf[i] = nand_id.ids[sizeof (nand_id.ids) -1 - i]; + nand_id.idh =readw (host->reg_base +LOONGSON_NAND_IDH_STATUS ); + +for (i =0 ; i <min (host->data->max_id_cycle, op.orig_len); i++) + op.buf[i] = nand_id.ids[host->data->max_id_cycle -1 - i];return ret; }@@ -676,6 +686,10 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)if (IS_ERR (host->regmap))return dev_err_probe (dev,PTR_ERR (host->regmap),"failed to init regmap\n" ); +if (host->data->id_cycle_field) +regmap_update_bits (host->regmap,LOONGSON_NAND_PARAM , host->data->id_cycle_field, + host->data->max_id_cycle <<__ffs (host->data->id_cycle_field)); + chan =dma_request_chan (dev,"rxtx" );if (IS_ERR (chan))return dev_err_probe (dev,PTR_ERR (chan),"failed to request DMA channel\n" );@@ -800,6 +814,7 @@ static void loongson_nand_remove(struct platform_device *pdev) }static const struct loongson_nand_data ls1b_nand_data = { + .max_id_cycle =5 , .status_field =GENMASK (15 ,8 ), .hold_cycle =0x2 , .wait_cycle =0xc ,@@ -807,6 +822,8 @@ static const struct loongson_nand_data ls1b_nand_data = { };static const struct loongson_nand_data ls1c_nand_data = { + .max_id_cycle =6 , + .id_cycle_field =GENMASK (14 ,12 ), .status_field =GENMASK (23 ,16 ), .op_scope_field =GENMASK (29 ,16 ), .hold_cycle =0x2 , --2.47.3
Keguang Zhang
maintainerRe: [PATCH v2 3/8] mtd: rawnand: loongson: Add 6-byte NAND ID reading support
Quoted 59 lines · Huacai Chen
Hi, Binbin,
Quoted 55 lines · Binbin Zhou
From: Keguang Zhang <[email protected]>
Loongson-1C and Loongson-2K SoCs support NAND flash chips with 6-byte ID. However, the current implementation only handles 5-byte ID which can lead to incorrect chip detection.
Extend
loongson_nand_read_id_type_exec()to support 6-byte NAND ID.Signed-off-by Keguang Zhang <[email protected]>Signed-off-by Binbin Zhou <[email protected]>--- .../mtd/nand/raw/loongson-nand-controller.c | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-)drivers/mtd/nand/raw/loongson-nand-controller.c +7
-2@@ -50,6 +50,9 @@#define LOONGSON_NAND_COL_ADDR_CYC 2U#define LOONGSON_NAND_MAX_ADDR_CYC 5U +#define LOONGSON_NAND_READ_ID_SLEEP_US 1000 +#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000 +#define BITS_PER_WORD (4 * BITS_PER_BYTE)struct loongson_nand_host ;@@ -73,6 +76,8 @@ struct loongson_nand_op { };struct loongson_nand_data { +unsigned int max_id_cycle; +unsigned int id_cycle_field;unsigned int status_field;unsigned int op_scope_field;unsigned int hold_cycle;@@ -458,10 +463,10 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const structstruct loongson_nand_op op = {};int i, ret;union { -char ids[5 ]; +char ids[6 ];struct {int idl; -char idh; +u16 idh; }; } nand_id;@@ -469,11 +474,16 @@ static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const structif (ret)return ret;
Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_read_id_type_exec(struct nand_chip *chip, const struct · line 479
Quoted 5 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3
-2- nand_id.idl =readl (host->reg_base +LOONGSON_NAND_IDL ); - nand_id.idh =readb (host->reg_base +LOONGSON_NAND_IDH_STATUS ); + ret =regmap_read_poll_timeout (host->regmap,LOONGSON_NAND_IDL , nand_id.idl, nand_id.idl, +LOONGSON_NAND_READ_ID_SLEEP_US , +LOONGSON_NAND_READ_ID_TIMEOUT_US );The last two lines can be merged.
No, merging them would exceed 100 columns.
Quoted 45 lines
Huacai
Quoted 43 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +13
-3+if (ret) +return ret; -for (i =0 ; i <min (sizeof (nand_id.ids), op.orig_len); i++) - op.buf[i] = nand_id.ids[sizeof (nand_id.ids) -1 - i]; + nand_id.idh =readw (host->reg_base +LOONGSON_NAND_IDH_STATUS ); + +for (i =0 ; i <min (host->data->max_id_cycle, op.orig_len); i++) + op.buf[i] = nand_id.ids[host->data->max_id_cycle -1 - i];return ret; }@@ -676,6 +686,10 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)if (IS_ERR (host->regmap))return dev_err_probe (dev,PTR_ERR (host->regmap),"failed to init regmap\n" ); +if (host->data->id_cycle_field) +regmap_update_bits (host->regmap,LOONGSON_NAND_PARAM , host->data->id_cycle_field, + host->data->max_id_cycle <<__ffs (host->data->id_cycle_field)); + chan =dma_request_chan (dev,"rxtx" );if (IS_ERR (chan))return dev_err_probe (dev,PTR_ERR (chan),"failed to request DMA channel\n" );@@ -800,6 +814,7 @@ static void loongson_nand_remove(struct platform_device *pdev) }static const struct loongson_nand_data ls1b_nand_data = { + .max_id_cycle =5 , .status_field =GENMASK (15 ,8 ), .hold_cycle =0x2 , .wait_cycle =0xc ,@@ -807,6 +822,8 @@ static const struct loongson_nand_data ls1b_nand_data = { };static const struct loongson_nand_data ls1c_nand_data = { + .max_id_cycle =6 , + .id_cycle_field =GENMASK (14 ,12 ), .status_field =GENMASK (23 ,16 ), .op_scope_field =GENMASK (29 ,16 ), .hold_cycle =0x2 , --2.47.3
Signature · 3 lines
Best regards, Keguang Zhang
PATCH v2 4/8 mtd: rawnand: loongson: Add nand chip select support
In reply to Binbin ZhouThe page address register describes the page address of the starting address for NAND read/write/erase operations.
According to the manual, it consists of two parts:
{chip select, page number}The chip select is fixed at 2 bits, and the page number is determined based on the actual capacity of the single-chip memory. Therefore we need to determine the chip select bits base on the page number.
For example, for a 1GB capacity chip (2K page size), it has 1M pages. Thus, [19:0] is used to represent the page number, and [21:20] represents the chip select.
--- .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++---- 1 file changed, 103 insertions(+), 30 deletions(-)
drivers/mtd/nand/raw/loongson-nand-controller.c +103 -30
@@ -82,6 +82,7 @@ struct loongson_nand_data {unsigned int op_scope_field;unsigned int hold_cycle;unsigned int wait_cycle; +unsigned int nand_cs;void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); };
@@ -90,6 +91,7 @@ struct loongson_nand_host {struct nand_chip chip;struct nand_controller controller;const struct loongson_nand_data *data; +unsigned int addr_cs_field;void __iomem *reg_base;struct regmap *regmap;/* DMA Engine stuff */
@@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const structreturn 0 ; } +static void loongson_nand_set_addr_cs (struct loongson_nand_host *host) +{ +struct nand_chip *chip = &host->chip; +struct mtd_info *mtd =nand_to_mtd (chip); + +if (!host->data->nand_cs) +return ; + +/* +* The Manufacturer/Chip ID read operation precedes attach_chip, at which point +* information such as NAND chip selection and capacity is unknown. As a +* workaround, we use 128MB cellsize (2KB pagesize) as a fallback. +*/ +if (!mtd->writesize) + host->addr_cs_field =GENMASK (17 ,16 ); + +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , host->addr_cs_field, + host->data->nand_cs <<__ffs (host->addr_cs_field)); +} +static void ls1b_nand_set_addr (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;
@@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , mask, val); } } + +loongson_nand_set_addr_cs (host); }static void loongson_nand_trigger_op (struct loongson_nand_host *host,struct loongson_nand_op *op)
@@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_operareturn nand_op_parser_exec_op (chip, &loongson_nand_op_parser, op, check_only); } -static int loongson_nand_attach_chip (struct nand_chip *chip) +static int loongson_nand_get_chip_capacity (struct nand_chip *chip) {struct loongson_nand_host *host =nand_get_controller_data (chip);u64 chipsize =nanddev_target_size (&chip->base); -int cell_size =0 ; +struct mtd_info *mtd =nand_to_mtd (chip); -switch (chipsize) { -case SZ_128M : - cell_size =0x0 ; -break ; -case SZ_256M : - cell_size =0x1 ; -break ; -case SZ_512M : - cell_size =0x2 ; -break ; -case SZ_1G : - cell_size =0x3 ; -break ; -case SZ_2G : - cell_size =0x4 ; -break ; -case SZ_4G : - cell_size =0x5 ; -break ; -case SZ_8G : - cell_size =0x6 ; -break ; -case SZ_16G : - cell_size =0x7 ; -break ; -default : -dev_err (host->dev,"unsupported chip size: %llu MB\n" , chipsize); -return -EINVAL ; +if (mtd->writesize ==SZ_4K && chipsize ==SZ_2G ) { + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x4 ; } +if (mtd->writesize ==SZ_2K ) { +switch (chipsize) { +case SZ_128M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0 ; +case SZ_256M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0x1 ; +case SZ_512M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0x2 ; +case SZ_1G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x3 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_8K ) { +switch (chipsize) { +case SZ_4G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x5 ; +case SZ_8G : + host->addr_cs_field =GENMASK (21 ,20 ); +return 0x6 ; +case SZ_16G : + host->addr_cs_field =GENMASK (22 ,21 ); +return 0x7 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_512 ) { +switch (chipsize) { +case SZ_8M : + host->addr_cs_field =GENMASK (15 ,14 ); +return 0x9 ; +case SZ_16M : + host->addr_cs_field =GENMASK (16 ,15 ); +return 0xa ; +case SZ_32M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0xb ; +case SZ_64M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0xc ; +case SZ_128M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0xd ; +default : + goto err; + } + } + +err: +dev_err (host->dev,"Unsupported chip size: %llu MB with page size %u B\n" , + chipsize, mtd->writesize); +return -EINVAL ; +} + +static int loongson_nand_attach_chip (struct nand_chip *chip) +{ +struct loongson_nand_host *host =nand_get_controller_data (chip); +int cell_size =0 ; + + cell_size =loongson_nand_get_chip_capacity (chip); +if (cell_size <0 ) +return cell_size; +switch (chip->ecc.engine_type) {case NAND_ECC_ENGINE_TYPE_NONE :break ;
@@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = { .status_field = GENMASK(15, 8), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1b_nand_set_addr, };
@@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = { .op_scope_field = GENMASK(29, 16), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1c_nand_set_addr, };
Signature · 1 line
2.47.3
Huacai Chen
maintainerRe: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
Hi, Binbin,
Quoted 111 lines · Binbin Zhou
The page address register describes the page address of the starting address for NAND read/write/erase operations.
According to the manual, it consists of two parts:
{chip select, page number}The
chip selectis fixed at 2 bits, and thepage numberis determined based on the actual capacity of the single-chip memory. Therefore we need to determine thechip selectbits base on thepage number.For example, for a 1GB capacity chip (2K page size), it has 1M pages. Thus, [19:0] is used to represent the page number, and [21:20] represents the chip select.
Signed-off-by Binbin Zhou <[email protected]>--- .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++---- 1 file changed, 103 insertions(+), 30 deletions(-)drivers/mtd/nand/raw/loongson-nand-controller.c +26
-24@@ -82,6 +82,7 @@ struct loongson_nand_data {unsigned int op_scope_field;unsigned int hold_cycle;unsigned int wait_cycle; +unsigned int nand_cs;void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); };@@ -90,6 +91,7 @@ struct loongson_nand_host {struct nand_chip chip;struct nand_controller controller;const struct loongson_nand_data *data; +unsigned int addr_cs_field;void __iomem *reg_base;struct regmap *regmap;/* DMA Engine stuff */ @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const structreturn 0 ; } +static void loongson_nand_set_addr_cs (struct loongson_nand_host *host) +{ +struct nand_chip *chip = &host->chip; +struct mtd_info *mtd =nand_to_mtd (chip); + +if (!host->data->nand_cs) +return ; + +/* +* The Manufacturer/Chip ID read operation precedes attach_chip, at which point +* information such as NAND chip selection and capacity is unknown. As a +* workaround, we use 128MB cellsize (2KB pagesize) as a fallback. +*/ +if (!mtd->writesize) + host->addr_cs_field =GENMASK (17 ,16 ); + +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , host->addr_cs_field, + host->data->nand_cs <<__ffs (host->addr_cs_field)); +} +static void ls1b_nand_set_addr (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;@@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , mask, val); } } + +loongson_nand_set_addr_cs (host); }static void loongson_nand_trigger_op (struct loongson_nand_host *host,struct loongson_nand_op *op)@@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_operareturn nand_op_parser_exec_op (chip, &loongson_nand_op_parser, op, check_only); } -static int loongson_nand_attach_chip (struct nand_chip *chip) +static int loongson_nand_get_chip_capacity (struct nand_chip *chip) {struct loongson_nand_host *host =nand_get_controller_data (chip);u64 chipsize =nanddev_target_size (&chip->base); -int cell_size =0 ; +struct mtd_info *mtd =nand_to_mtd (chip); -switch (chipsize) { -case SZ_128M : - cell_size =0x0 ; -break ; -case SZ_256M : - cell_size =0x1 ; -break ; -case SZ_512M : - cell_size =0x2 ; -break ; -case SZ_1G : - cell_size =0x3 ; -break ; -case SZ_2G : - cell_size =0x4 ; -break ; -case SZ_4G : - cell_size =0x5 ; -break ; -case SZ_8G : - cell_size =0x6 ; -break ;
drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera · line 639
Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3
-6-case SZ_16G : - cell_size =0x7 ; -break ; -default : -dev_err (host->dev,"unsupported chip size: %llu MB\n" , chipsize); -return -EINVAL ; +if (mtd->writesize ==SZ_4K && chipsize ==SZ_2G ) { + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x4 ; }
I think you want to sort this part by the return value, but "return 0x4" has already break it.
So I think it is better to use a big switch-case for writesize, and sort the big switch-case by writesize.
Huacai
Quoted 96 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +74
-1+if (mtd->writesize ==SZ_2K ) { +switch (chipsize) { +case SZ_128M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0 ; +case SZ_256M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0x1 ; +case SZ_512M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0x2 ; +case SZ_1G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x3 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_8K ) { +switch (chipsize) { +case SZ_4G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x5 ; +case SZ_8G : + host->addr_cs_field =GENMASK (21 ,20 ); +return 0x6 ; +case SZ_16G : + host->addr_cs_field =GENMASK (22 ,21 ); +return 0x7 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_512 ) { +switch (chipsize) { +case SZ_8M : + host->addr_cs_field =GENMASK (15 ,14 ); +return 0x9 ; +case SZ_16M : + host->addr_cs_field =GENMASK (16 ,15 ); +return 0xa ; +case SZ_32M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0xb ; +case SZ_64M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0xc ; +case SZ_128M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0xd ; +default : + goto err; + } + } + +err: +dev_err (host->dev,"Unsupported chip size: %llu MB with page size %u B\n" , + chipsize, mtd->writesize); +return -EINVAL ; +} + +static int loongson_nand_attach_chip (struct nand_chip *chip) +{ +struct loongson_nand_host *host =nand_get_controller_data (chip); +int cell_size =0 ; + + cell_size =loongson_nand_get_chip_capacity (chip); +if (cell_size <0 ) +return cell_size; +switch (chip->ecc.engine_type) {case NAND_ECC_ENGINE_TYPE_NONE :break ;@@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = { .status_field = GENMASK(15, 8), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1b_nand_set_addr, };@@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = { .op_scope_field = GENMASK(29, 16), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1c_nand_set_addr, }; --2.47.3
Re: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
Hi:
Quoted 128 lines · Huacai Chen
Hi, Binbin,
Quoted 111 lines · Binbin Zhou
The page address register describes the page address of the starting address for NAND read/write/erase operations.
According to the manual, it consists of two parts:
{chip select, page number}The
chip selectis fixed at 2 bits, and thepage numberis determined based on the actual capacity of the single-chip memory. Therefore we need to determine thechip selectbits base on thepage number.For example, for a 1GB capacity chip (2K page size), it has 1M pages. Thus, [19:0] is used to represent the page number, and [21:20] represents the chip select.
Signed-off-by Binbin Zhou <[email protected]>--- .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++---- 1 file changed, 103 insertions(+), 30 deletions(-)drivers/mtd/nand/raw/loongson-nand-controller.c +26
-24@@ -82,6 +82,7 @@ struct loongson_nand_data {unsigned int op_scope_field;unsigned int hold_cycle;unsigned int wait_cycle; +unsigned int nand_cs;void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); };@@ -90,6 +91,7 @@ struct loongson_nand_host {struct nand_chip chip;struct nand_controller controller;const struct loongson_nand_data *data; +unsigned int addr_cs_field;void __iomem *reg_base;struct regmap *regmap;/* DMA Engine stuff */ @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const structreturn 0 ; } +static void loongson_nand_set_addr_cs (struct loongson_nand_host *host) +{ +struct nand_chip *chip = &host->chip; +struct mtd_info *mtd =nand_to_mtd (chip); + +if (!host->data->nand_cs) +return ; + +/* +* The Manufacturer/Chip ID read operation precedes attach_chip, at which point +* information such as NAND chip selection and capacity is unknown. As a +* workaround, we use 128MB cellsize (2KB pagesize) as a fallback. +*/ +if (!mtd->writesize) + host->addr_cs_field =GENMASK (17 ,16 ); + +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , host->addr_cs_field, + host->data->nand_cs <<__ffs (host->addr_cs_field)); +} +static void ls1b_nand_set_addr (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;@@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , mask, val); } } + +loongson_nand_set_addr_cs (host); }static void loongson_nand_trigger_op (struct loongson_nand_host *host,struct loongson_nand_op *op)@@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_operareturn nand_op_parser_exec_op (chip, &loongson_nand_op_parser, op, check_only); } -static int loongson_nand_attach_chip (struct nand_chip *chip) +static int loongson_nand_get_chip_capacity (struct nand_chip *chip) {struct loongson_nand_host *host =nand_get_controller_data (chip);u64 chipsize =nanddev_target_size (&chip->base); -int cell_size =0 ; +struct mtd_info *mtd =nand_to_mtd (chip); -switch (chipsize) { -case SZ_128M : - cell_size =0x0 ; -break ; -case SZ_256M : - cell_size =0x1 ; -break ; -case SZ_512M : - cell_size =0x2 ; -break ; -case SZ_1G : - cell_size =0x3 ; -break ; -case SZ_2G : - cell_size =0x4 ; -break ; -case SZ_4G : - cell_size =0x5 ; -break ; -case SZ_8G : - cell_size =0x6 ; -break ;drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera · line 639
Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3
-6-case SZ_16G : - cell_size =0x7 ; -break ; -default : -dev_err (host->dev,"unsupported chip size: %llu MB\n" , chipsize); -return -EINVAL ; +if (mtd->writesize ==SZ_4K && chipsize ==SZ_2G ) { + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x4 ; }I think you want to sort this part by the return value, but "return
0x4" has already break it.
Quoted 2 lines
So I think it is better to use a big switch-case for writesize, and sort the big switch-case by writesize.
How about:
switch (mtd->writesize) {
case SZ_512:
switch (chipsize) {
case SZ_8M:
host->addr_cs_field = GENMASK(15, 14);
return 0x9;
case SZ_16M:
host->addr_cs_field = GENMASK(16, 15);
return 0xa;
case SZ_32M:
host->addr_cs_field = GENMASK(17, 16);
return 0xb;
case SZ_64M:
host->addr_cs_field = GENMASK(18, 17);
return 0xc;
case SZ_128M:
host->addr_cs_field = GENMASK(19, 18);
return 0xd;
}
break;
case SZ_2K:
switch (chipsize) {
case SZ_128M:
host->addr_cs_field = GENMASK(17, 16);
return 0;
case SZ_256M:
host->addr_cs_field = GENMASK(18, 17);
return 0x1;
case SZ_512M:
host->addr_cs_field = GENMASK(19, 18);
return 0x2;
case SZ_1G:
host->addr_cs_field = GENMASK(20, 19);
return 0x3;
}
break;
case SZ_4K:
if (chipsize == SZ_2G) {
host->addr_cs_field = GENMASK(20, 19);
return 0x4;
}
break;
case SZ_8K:
switch (chipsize) {
case SZ_4G:
host->addr_cs_field = GENMASK(20, 19);
return 0x5;
case SZ_8G:
host->addr_cs_field = GENMASK(21, 20);
return 0x6;
case SZ_16G:
host->addr_cs_field = GENMASK(22, 21);
return 0x7;
}
break;
default:
break;
}
dev_err(host->dev, "Unsupported chip size: %llu MB with page
size %u B\n",
chipsize, mtd->writesize);Quoted 99 lines
Huacai
Quoted 96 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +74
-1+if (mtd->writesize ==SZ_2K ) { +switch (chipsize) { +case SZ_128M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0 ; +case SZ_256M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0x1 ; +case SZ_512M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0x2 ; +case SZ_1G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x3 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_8K ) { +switch (chipsize) { +case SZ_4G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x5 ; +case SZ_8G : + host->addr_cs_field =GENMASK (21 ,20 ); +return 0x6 ; +case SZ_16G : + host->addr_cs_field =GENMASK (22 ,21 ); +return 0x7 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_512 ) { +switch (chipsize) { +case SZ_8M : + host->addr_cs_field =GENMASK (15 ,14 ); +return 0x9 ; +case SZ_16M : + host->addr_cs_field =GENMASK (16 ,15 ); +return 0xa ; +case SZ_32M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0xb ; +case SZ_64M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0xc ; +case SZ_128M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0xd ; +default : + goto err; + } + } + +err: +dev_err (host->dev,"Unsupported chip size: %llu MB with page size %u B\n" , + chipsize, mtd->writesize); +return -EINVAL ; +} + +static int loongson_nand_attach_chip (struct nand_chip *chip) +{ +struct loongson_nand_host *host =nand_get_controller_data (chip); +int cell_size =0 ; + + cell_size =loongson_nand_get_chip_capacity (chip); +if (cell_size <0 ) +return cell_size; +switch (chip->ecc.engine_type) {case NAND_ECC_ENGINE_TYPE_NONE :break ;@@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = { .status_field = GENMASK(15, 8), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1b_nand_set_addr, };@@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = { .op_scope_field = GENMASK(29, 16), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1c_nand_set_addr, }; --2.47.3
Signature · 2 lines
Thanks. Binbin
Huacai Chen
maintainerRe: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
Quoted 154 lines · Binbin Zhou
Hi:
Quoted 128 lines · Huacai Chen
Hi, Binbin,
Quoted 111 lines · Binbin Zhou
The page address register describes the page address of the starting address for NAND read/write/erase operations.
According to the manual, it consists of two parts:
{chip select, page number}The
chip selectis fixed at 2 bits, and thepage numberis determined based on the actual capacity of the single-chip memory. Therefore we need to determine thechip selectbits base on thepage number.For example, for a 1GB capacity chip (2K page size), it has 1M pages. Thus, [19:0] is used to represent the page number, and [21:20] represents the chip select.
Signed-off-by Binbin Zhou <[email protected]>--- .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++---- 1 file changed, 103 insertions(+), 30 deletions(-)drivers/mtd/nand/raw/loongson-nand-controller.c +26
-24@@ -82,6 +82,7 @@ struct loongson_nand_data {unsigned int op_scope_field;unsigned int hold_cycle;unsigned int wait_cycle; +unsigned int nand_cs;void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); };@@ -90,6 +91,7 @@ struct loongson_nand_host {struct nand_chip chip;struct nand_controller controller;const struct loongson_nand_data *data; +unsigned int addr_cs_field;void __iomem *reg_base;struct regmap *regmap;/* DMA Engine stuff */ @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const structreturn 0 ; } +static void loongson_nand_set_addr_cs (struct loongson_nand_host *host) +{ +struct nand_chip *chip = &host->chip; +struct mtd_info *mtd =nand_to_mtd (chip); + +if (!host->data->nand_cs) +return ; + +/* +* The Manufacturer/Chip ID read operation precedes attach_chip, at which point +* information such as NAND chip selection and capacity is unknown. As a +* workaround, we use 128MB cellsize (2KB pagesize) as a fallback. +*/ +if (!mtd->writesize) + host->addr_cs_field =GENMASK (17 ,16 ); + +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , host->addr_cs_field, + host->data->nand_cs <<__ffs (host->addr_cs_field)); +} +static void ls1b_nand_set_addr (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;@@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , mask, val); } } + +loongson_nand_set_addr_cs (host); }static void loongson_nand_trigger_op (struct loongson_nand_host *host,struct loongson_nand_op *op)@@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_operareturn nand_op_parser_exec_op (chip, &loongson_nand_op_parser, op, check_only); } -static int loongson_nand_attach_chip (struct nand_chip *chip) +static int loongson_nand_get_chip_capacity (struct nand_chip *chip) {struct loongson_nand_host *host =nand_get_controller_data (chip);u64 chipsize =nanddev_target_size (&chip->base); -int cell_size =0 ; +struct mtd_info *mtd =nand_to_mtd (chip); -switch (chipsize) { -case SZ_128M : - cell_size =0x0 ; -break ; -case SZ_256M : - cell_size =0x1 ; -break ; -case SZ_512M : - cell_size =0x2 ; -break ; -case SZ_1G : - cell_size =0x3 ; -break ; -case SZ_2G : - cell_size =0x4 ; -break ; -case SZ_4G : - cell_size =0x5 ; -break ; -case SZ_8G : - cell_size =0x6 ; -break ;drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_opera · line 639
Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3
-6-case SZ_16G : - cell_size =0x7 ; -break ; -default : -dev_err (host->dev,"unsupported chip size: %llu MB\n" , chipsize); -return -EINVAL ; +if (mtd->writesize ==SZ_4K && chipsize ==SZ_2G ) { + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x4 ; }I think you want to sort this part by the return value, but "return
0x4" has already break it.Quoted 2 lines
So I think it is better to use a big switch-case for writesize, and sort the big switch-case by writesize.
How about:
switch (mtd->writesize) { case SZ_512: switch (chipsize) { case SZ_8M: host->addr_cs_field = GENMASK(15, 14); return 0x9; case SZ_16M: host->addr_cs_field = GENMASK(16, 15); return 0xa; case SZ_32M: host->addr_cs_field = GENMASK(17, 16); return 0xb; case SZ_64M: host->addr_cs_field = GENMASK(18, 17); return 0xc; case SZ_128M: host->addr_cs_field = GENMASK(19, 18);
Quoted 8 lines
return 0xd;
}
break;
case SZ_2K:
switch (chipsize) {
case SZ_128M:
host->addr_cs_field = GENMASK(17, 16);
return 0;Use 0x0 for consistency.
Quoted 24 lines
case SZ_256M:
host->addr_cs_field = GENMASK(18, 17);
return 0x1;
case SZ_512M:
host->addr_cs_field = GENMASK(19, 18);
return 0x2;
case SZ_1G:
host->addr_cs_field = GENMASK(20, 19);
return 0x3;
}
break;
case SZ_4K:
if (chipsize == SZ_2G) {
host->addr_cs_field = GENMASK(20, 19);
return 0x4;
}
break;
case SZ_8K:
switch (chipsize) {
case SZ_4G:
host->addr_cs_field = GENMASK(20, 19);
return 0x5;
case SZ_8G:
host->addr_cs_field = GENMASK(21, 20);Quoted 8 lines
return 0x6;
case SZ_16G:
host->addr_cs_field = GENMASK(22, 21);
return 0x7;
}
break;
default:
break;The default branch is unneeded. Others are OK for me.
Huacai
Quoted 108 lines
} dev_err(host->dev, "Unsupported chip size: %llu MB with page size %u B\n", chipsize, mtd->writesize);Quoted 95 lines
Huacai
Quoted 92 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +74
-0+if (mtd->writesize ==SZ_2K ) { +switch (chipsize) { +case SZ_128M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0 ; +case SZ_256M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0x1 ; +case SZ_512M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0x2 ; +case SZ_1G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x3 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_8K ) { +switch (chipsize) { +case SZ_4G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x5 ; +case SZ_8G : + host->addr_cs_field =GENMASK (21 ,20 ); +return 0x6 ; +case SZ_16G : + host->addr_cs_field =GENMASK (22 ,21 ); +return 0x7 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_512 ) { +switch (chipsize) { +case SZ_8M : + host->addr_cs_field =GENMASK (15 ,14 ); +return 0x9 ; +case SZ_16M : + host->addr_cs_field =GENMASK (16 ,15 ); +return 0xa ; +case SZ_32M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0xb ; +case SZ_64M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0xc ; +case SZ_128M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0xd ; +default : + goto err; + } + } + +err: +dev_err (host->dev,"Unsupported chip size: %llu MB with page size %u B\n" , + chipsize, mtd->writesize); +return -EINVAL ; +} + +static int loongson_nand_attach_chip (struct nand_chip *chip) +{ +struct loongson_nand_host *host =nand_get_controller_data (chip); +int cell_size =0 ; + + cell_size =loongson_nand_get_chip_capacity (chip); +if (cell_size <0 ) +return cell_size; +switch (chip->ecc.engine_type) {case NAND_ECC_ENGINE_TYPE_NONE :break ;@@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = { .status_field = GENMASK(15, 8), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1b_nand_set_addr, };@@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = { .op_scope_field = GENMASK(29, 16), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0, .set_addr = ls1c_nand_set_addr, };Quoted 4 lines
Quoted 4 lines
--
2.47.3--
Thanks.
Binbin
Keguang Zhang
maintainerRe: [PATCH v2 4/8] mtd: rawnand: loongson: Add nand chip select support
In reply to Binbin ZhouQuoted 198 lines · Binbin Zhou
The page address register describes the page address of the starting address for NAND read/write/erase operations.
According to the manual, it consists of two parts:
{chip select, page number}The
chip selectis fixed at 2 bits, and thepage numberis determined based on the actual capacity of the single-chip memory. Therefore we need to determine thechip selectbits base on thepage number.For example, for a 1GB capacity chip (2K page size), it has 1M pages. Thus, [19:0] is used to represent the page number, and [21:20] represents the chip select.
Signed-off-by Binbin Zhou <[email protected]>--- .../mtd/nand/raw/loongson-nand-controller.c | 133 ++++++++++++++---- 1 file changed, 103 insertions(+), 30 deletions(-)drivers/mtd/nand/raw/loongson-nand-controller.c +101
-30@@ -82,6 +82,7 @@ struct loongson_nand_data {unsigned int op_scope_field;unsigned int hold_cycle;unsigned int wait_cycle; +unsigned int nand_cs;void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); };@@ -90,6 +91,7 @@ struct loongson_nand_host {struct nand_chip chip;struct nand_controller controller;const struct loongson_nand_data *data; +unsigned int addr_cs_field;void __iomem *reg_base;struct regmap *regmap;/* DMA Engine stuff */ @@ -215,6 +217,26 @@ static int loongson_nand_parse_instructions(struct nand_chip *chip, const structreturn 0 ; } +static void loongson_nand_set_addr_cs (struct loongson_nand_host *host) +{ +struct nand_chip *chip = &host->chip; +struct mtd_info *mtd =nand_to_mtd (chip); + +if (!host->data->nand_cs) +return ; + +/* +* The Manufacturer/Chip ID read operation precedes attach_chip, at which point +* information such as NAND chip selection and capacity is unknown. As a +* workaround, we use 128MB cellsize (2KB pagesize) as a fallback. +*/ +if (!mtd->writesize) + host->addr_cs_field =GENMASK (17 ,16 ); + +regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , host->addr_cs_field, + host->data->nand_cs <<__ffs (host->addr_cs_field)); +} +static void ls1b_nand_set_addr (struct loongson_nand_host *host,struct loongson_nand_op *op) {struct nand_chip *chip = &host->chip;@@ -263,6 +285,8 @@ static void ls1c_nand_set_addr(struct loongson_nand_host *host, struct loongson_regmap_update_bits (host->regmap,LOONGSON_NAND_ADDR2 , mask, val); } } + +loongson_nand_set_addr_cs (host); }static void loongson_nand_trigger_op (struct loongson_nand_host *host,struct loongson_nand_op *op)@@ -603,42 +627,89 @@ static int loongson_nand_exec_op(struct nand_chip *chip, const struct nand_operareturn nand_op_parser_exec_op (chip, &loongson_nand_op_parser, op, check_only); } -static int loongson_nand_attach_chip (struct nand_chip *chip) +static int loongson_nand_get_chip_capacity (struct nand_chip *chip) {struct loongson_nand_host *host =nand_get_controller_data (chip);u64 chipsize =nanddev_target_size (&chip->base); -int cell_size =0 ; +struct mtd_info *mtd =nand_to_mtd (chip); -switch (chipsize) { -case SZ_128M : - cell_size =0x0 ; -break ; -case SZ_256M : - cell_size =0x1 ; -break ; -case SZ_512M : - cell_size =0x2 ; -break ; -case SZ_1G : - cell_size =0x3 ; -break ; -case SZ_2G : - cell_size =0x4 ; -break ; -case SZ_4G : - cell_size =0x5 ; -break ; -case SZ_8G : - cell_size =0x6 ; -break ; -case SZ_16G : - cell_size =0x7 ; -break ; -default : -dev_err (host->dev,"unsupported chip size: %llu MB\n" , chipsize); -return -EINVAL ; +if (mtd->writesize ==SZ_4K && chipsize ==SZ_2G ) { + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x4 ; } +if (mtd->writesize ==SZ_2K ) { +switch (chipsize) { +case SZ_128M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0 ; +case SZ_256M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0x1 ; +case SZ_512M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0x2 ; +case SZ_1G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x3 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_8K ) { +switch (chipsize) { +case SZ_4G : + host->addr_cs_field =GENMASK (20 ,19 ); +return 0x5 ; +case SZ_8G : + host->addr_cs_field =GENMASK (21 ,20 ); +return 0x6 ; +case SZ_16G : + host->addr_cs_field =GENMASK (22 ,21 ); +return 0x7 ; +default : + goto err; + } + } + +if (mtd->writesize ==SZ_512 ) { +switch (chipsize) { +case SZ_8M : + host->addr_cs_field =GENMASK (15 ,14 ); +return 0x9 ; +case SZ_16M : + host->addr_cs_field =GENMASK (16 ,15 ); +return 0xa ; +case SZ_32M : + host->addr_cs_field =GENMASK (17 ,16 ); +return 0xb ; +case SZ_64M : + host->addr_cs_field =GENMASK (18 ,17 ); +return 0xc ; +case SZ_128M : + host->addr_cs_field =GENMASK (19 ,18 ); +return 0xd ; +default : + goto err; + } + } + +err: +dev_err (host->dev,"Unsupported chip size: %llu MB with page size %u B\n" , + chipsize, mtd->writesize); +return -EINVAL ; +} + +static int loongson_nand_attach_chip (struct nand_chip *chip) +{ +struct loongson_nand_host *host =nand_get_controller_data (chip); +int cell_size =0 ; + + cell_size =loongson_nand_get_chip_capacity (chip); +if (cell_size <0 ) +return cell_size; +switch (chip->ecc.engine_type) {case NAND_ECC_ENGINE_TYPE_NONE :break ;
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 892
Quoted 4 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0@@ -818,6 +889,7 @@ static const struct loongson_nand_data ls1b_nand_data = { .status_field = GENMASK(15, 8), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0,
The assignment .nand_cs = 0x0 is redundant and can be removed.
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 903
Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0.set_addr = ls1b_nand_set_addr, };@@ -828,6 +900,7 @@ static const struct loongson_nand_data ls1c_nand_data = { .op_scope_field = GENMASK(29, 16), .hold_cycle = 0x2, .wait_cycle = 0xc, + .nand_cs = 0x0,
Ditto.
Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0
-1.set_addr = ls1c_nand_set_addr, }; --2.47.3
Signature · 3 lines
Best regards, Keguang Zhang
PATCH v2 5/8 dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
In reply to Binbin ZhouAdd new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.
--- .../bindings/mtd/loongson,ls1b-nand-controller.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml +4 -2
@@ -4,13 +4,14 @@ $id: http://devicetree.org/schemas/mtd/loongson,ls1b-nand-controller.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Loongson-1 NAND Controller +title: Loongson NAND Controller maintainers: - Keguang Zhang <[email protected]> + - Binbin Zhou <[email protected]> description: - The Loongson-1 NAND controller abstracts all supported operations, + The Loongson NAND controller abstracts all supported operations, meaning it does not support low-level access to raw NAND flash chips. Moreover, the controller is paired with the DMA engine to perform READ and PROGRAM functions.
@@ -24,6 +25,7 @@ properties: - enum: - loongson,ls1b-nand-controller - loongson,ls1c-nand-controller + - loongson,ls2k0500-nand-controller - items: - enum: - loongson,ls1a-nand-controller
Signature · 1 line
2.47.3
Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
Quoted 4 lines · Binbin Zhou
Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.
Why do you add quotes?
Best regards,
Krzysztof
Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
Hi Krzysztof:
Quoted 9 lines · Krzysztof Kozlowski
Quoted 4 lines · Binbin Zhou
Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.
Why do you add quotes?
Emm...
Sorry, I didn't notice that.
I reacquired the V1 patchset using “b4 am xxx” to avoid manually adding tags. I believe it may be caused by the b4 command.
Quoted 3 lines
Best regards,
Krzysztof
--
Thanks.
Binbin
Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
Quoted 11 lines · Binbin Zhou
Hi Krzysztof:
Quoted 8 lines · Krzysztof Kozlowski
Quoted 4 lines · Binbin Zhou
Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.
Quoted 6 lines
Quoted 1 line
Why do you add quotes?
Emm...
Sorry, I didn't notice that.
I reacquired the V1 patchset using “b4 am xxx” to avoid manually adding tags. I believe it may be caused by theb4command.
Then aren't you using some old b4?
I just did it and look:
[PATCH v1 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
+ Acked-by: Rob Herring (Arm) <[email protected]> (✓ DKIM/kernel.org)
+ Link: https://lore.kernel.org/r/588639de591ada408bdaeb0d279c5d62a4b53d61.1753166096.git.zhoubinbin@loongson.cn
+ Signed-off-by: Krzysztof Kozlowski <[email protected]>
No quotes in commit msg either.
Best regards,
Krzysztof
Re: [PATCH v2 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
Hi Krzysztof:
Quoted 20 lines · Krzysztof Kozlowski
Quoted 11 lines · Binbin Zhou
Hi Krzysztof:
Quoted 8 lines · Krzysztof Kozlowski
Quoted 4 lines · Binbin Zhou
Add new compatible for the Loongson-2K NAND controller used for Loongson-2K0500 SoC.
Quoted 6 lines
Quoted 1 line
Why do you add quotes?
Emm...
Sorry, I didn't notice that.
I reacquired the V1 patchset using “b4 am xxx” to avoid manually adding tags. I believe it may be caused by theb4command.
Quoted 8 lines
Then aren't you using some old b4?
I just did it and look:
[PATCH v1 5/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K0500 NAND controller
+ Acked-by: Rob Herring (Arm) <[email protected]> (✓ DKIM/kernel.org)
+ Link: https://lore.kernel.org/r/588639de591ada408bdaeb0d279c5d62a4b53d61.1753166096.git.zhoubinbin@loongson.cn
+ Signed-off-by: Krzysztof Kozlowski <[email protected]>
Thanks for your reply and testing.
I rechecked my b4 repository, and it does need to be updated. It was my mistake. I will fix it in the next version.
Thanks again!
Quoted 7 lines
No quotes in commit msg either.
Best regards,
Krzysztof
Signature · 2 lines
Thanks. Binbin
PATCH v2 6/8 mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
In reply to Binbin ZhouThe Loongson-2K0500 NAND controller is similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum page size of 8KB, and it supports up to 4 chip selects and 4 RDY signals.
Its DMA controller is defaulted to APBDMA0.
--- drivers/mtd/nand/raw/Kconfig | 2 +- .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-)
drivers/mtd/nand/raw/Kconfig +1 -1
@@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35 config MTD_NAND_LOONGSON tristate "Loongson NAND controller" - depends on LOONGSON1_APB_DMA || COMPILE_TEST + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST select REGMAP_MMIO help Enables support for NAND controller on Loongson family chips.
drivers/mtd/nand/raw/loongson-nand-controller.c +53 -2
126 lines not on this page · raw message
Signature · 1 line
2.47.3
Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
Quoted 19 lines · Binbin Zhou
The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum page size of 8KB, and it supports up to 4 chip selects and 4 RDY signals.
Its DMA controller is defaulted to APBDMA0.
Signed-off-by Binbin Zhou <[email protected]>--- drivers/mtd/nand/raw/Kconfig | 2 +- .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-)drivers/mtd/nand/raw/Kconfig +0
-0
drivers/mtd/nand/raw/Kconfig config MTD_NAND_NUVOTON_MA35 · line 467
Quoted 5 lines
drivers/mtd/nand/raw/Kconfig +1
-1@@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35 config MTD_NAND_LOONGSON tristate "Loongson NAND controller" - depends on LOONGSON1_APB_DMA || COMPILE_TEST + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST
Why is this dependency necessary? I think the DMA operations are done through DMAengine API, and thus the consumer decouples with the DMA provider. If so, I think the depends line should be removed, instead of extended.
Regards,
Yao Zi
Quoted 3 lines
drivers/mtd/nand/raw/Kconfig +0
-0select REGMAP_MMIO help Enables support for NAND controller on Loongson family chips.
Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
HI Yao:
Thanks for your reply.
Quoted 22 lines · Yao Zi
Quoted 20 lines · Binbin Zhou
The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum page size of 8KB, and it supports up to 4 chip selects and 4 RDY signals.
Its DMA controller is defaulted to APBDMA0.
Signed-off-by Binbin Zhou <[email protected]>--- drivers/mtd/nand/raw/Kconfig | 2 +- .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-)drivers/mtd/nand/raw/Kconfig +0
-0@@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35
Quoted 9 lines
drivers/mtd/nand/raw/Kconfig config MTD_NAND_NUVOTON_MA35 · line 467
Quoted 4 lines
drivers/mtd/nand/raw/Kconfig +1
-1config MTD_NAND_LOONGSON tristate "Loongson NAND controller" - depends on LOONGSON1_APB_DMA || COMPILE_TEST + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TESTWhy is this dependency necessary? I think the DMA operations are done through DMAengine API, and thus the consumer decouples with the DMA provider. If so, I think the depends line should be removed, instead of extended.
This is an existing execution dependency. Although there is no guarantee that it will work with other DMA engines in the future, only this combination has been tested and proven to be correct at present. Therefore, I would still like to retain this dependency.
Quoted 7 lines
Regards,
Yao ZiQuoted 3 lines
drivers/mtd/nand/raw/Kconfig +0
-0select REGMAP_MMIO help Enables support for NAND controller on Loongson family chips.
Signature · 2 lines
Thanks. Binbin
Keguang Zhang
maintainerRe: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
In reply to Binbin ZhouQuoted 73 lines · Binbin Zhou
The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum page size of 8KB, and it supports up to 4 chip selects and 4 RDY signals.
Its DMA controller is defaulted to APBDMA0.
Signed-off-by Binbin Zhou <[email protected]>--- drivers/mtd/nand/raw/Kconfig | 2 +- .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-)drivers/mtd/nand/raw/Kconfig +1
-1@@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35 config MTD_NAND_LOONGSON tristate "Loongson NAND controller" - depends on LOONGSON1_APB_DMA || COMPILE_TEST + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST select REGMAP_MMIO help Enables support for NAND controller on Loongson family chips.drivers/mtd/nand/raw/loongson-nand-controller.c +19
-0@@ -3,6 +3,7 @@* NAND Controller Driver for Loongson family chips * * Copyright (C) 2015-2025 Keguang Zhang <[email protected]> +* Copyright (C) 2025 Binbin Zhou <[email protected]> */ #include <linux/kernel.h> @@ -26,6 +27,7 @@#define LOONGSON_NAND_IDH_STATUS 0x14#define LOONGSON_NAND_PARAM 0x18#define LOONGSON_NAND_OP_NUM 0x1c +#define LOONGSON_NAND_CS_RDY_MAP 0x20/* Bitfields of nand command register */ #define LOONGSON_NAND_CMD_OP_DONE BIT(10)@@ -40,6 +42,23 @@#define LOONGSON_NAND_CMD_READ BIT(1)#define LOONGSON_NAND_CMD_VALID BIT(0) +/* Bitfields of nand cs/rdy map register */ +#define LOONGSON_NAND_MAP_CS1_SEL GENMASK(11, 8) +#define LOONGSON_NAND_MAP_RDY1_SEL GENMASK(15, 12) +#define LOONGSON_NAND_MAP_CS2_SEL GENMASK(19, 16) +#define LOONGSON_NAND_MAP_RDY2_SEL GENMASK(23, 20) +#define LOONGSON_NAND_MAP_CS3_SEL GENMASK(27, 24) +#define LOONGSON_NAND_MAP_RDY3_SEL GENMASK(31, 28) + +#define LOONGSON_NAND_CS_SEL0 BIT(0) +#define LOONGSON_NAND_CS_SEL1 BIT(1) +#define LOONGSON_NAND_CS_SEL2 BIT(2) +#define LOONGSON_NAND_CS_SEL3 BIT(3) +#define LOONGSON_NAND_CS_RDY0 BIT(0) +#define LOONGSON_NAND_CS_RDY1 BIT(1) +#define LOONGSON_NAND_CS_RDY2 BIT(2) +#define LOONGSON_NAND_CS_RDY3 BIT(3) +/* Bitfields of nand timing register */ #define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)#define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)
drivers/mtd/nand/raw/loongson-nand-controller.c line 75
Quoted 4 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0@@ -53,6 +72,8 @@#define LOONGSON_NAND_READ_ID_SLEEP_US 1000#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000 +#define LOONGSON_NAND_64BIT_DMA BIT(0)
It's strongly suggested to replace this flag with a dma_bits field in loongson_nand_host.
Please see the comments below.
drivers/mtd/nand/raw/loongson-nand-controller.c struct loongson_nand_data { · line 106
Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0+#define BITS_PER_WORD (4 * BITS_PER_BYTE)struct loongson_nand_host ;@@ -83,6 +104,7 @@ struct loongson_nand_data {unsigned int hold_cycle;unsigned int wait_cycle;unsigned int nand_cs;
Add unsigned int dma_bits;
Quoted 14 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +2
-1+unsigned int flags;void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); };@@ -751,7 +773,7 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)struct device *dev = host->dev;struct dma_chan *chan;struct dma_slave_config cfg = {}; -int ret; +int ret, val; host->regmap =devm_regmap_init_mmio (dev, host->reg_base, &loongson_nand_regmap_config);if (IS_ERR (host->regmap))
drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 788
Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3
-0@@ -761,6 +783,9 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)regmap_update_bits (host->regmap,LOONGSON_NAND_PARAM , host->data->id_cycle_field, host->data->max_id_cycle <<__ffs (host->data->id_cycle_field)); +if (host->data->flags &LOONGSON_NAND_64BIT_DMA ) +dma_set_mask_and_coherent (dev,DMA_BIT_MASK (64 )); +
Sorry, all platforms should call dma_set_mask_and_coherent(), including Loongson-1, which I missed earlier.
ret = dma_set_mask_and_coherent(dev,
DMA_BIT_MASK(host->data->dma_bits));
if (ret)
return dev_err_probe(dev, ret, "failed to set DMA mask\n");Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0
-0chan =dma_request_chan (dev,"rxtx" );if (IS_ERR (chan))return dev_err_probe (dev,PTR_ERR (chan),"failed to request DMA channel\n" );@@ -776,7 +801,14 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)init_completion (&host->dma_complete);
drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 811
Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +8
-1-return 0 ; + val =FIELD_PREP (LOONGSON_NAND_MAP_CS1_SEL ,LOONGSON_NAND_CS_SEL1 ) + |FIELD_PREP (LOONGSON_NAND_MAP_RDY1_SEL ,LOONGSON_NAND_CS_RDY1 ) + |FIELD_PREP (LOONGSON_NAND_MAP_CS2_SEL ,LOONGSON_NAND_CS_SEL2 ) + |FIELD_PREP (LOONGSON_NAND_MAP_RDY2_SEL ,LOONGSON_NAND_CS_RDY2 ) + |FIELD_PREP (LOONGSON_NAND_MAP_CS3_SEL ,LOONGSON_NAND_CS_SEL3 ) + |FIELD_PREP (LOONGSON_NAND_MAP_RDY3_SEL ,LOONGSON_NAND_CS_RDY3 ); + +return regmap_write (host->regmap,LOONGSON_NAND_CS_RDY_MAP , val);
Chip selects should be set before requesting the DMA channel.
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 924
Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0
-0}static int loongson_nand_chip_init (struct loongson_nand_host *host)@@ -890,6 +922,7 @@ static const struct loongson_nand_data ls1b_nand_data = { .hold_cycle = 0x2, .wait_cycle = 0xc, .nand_cs = 0x0,
Add .dma_bits = 32,
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 925
Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0+ .flags = 0,
The assignment .flags = 0x0 is redundant and can be removed.
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 936
Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0
-0.set_addr = ls1b_nand_set_addr, };@@ -901,6 +934,19 @@ static const struct loongson_nand_data ls1c_nand_data = { .hold_cycle = 0x2, .wait_cycle = 0xc, .nand_cs = 0x0,
Add .dma_bits = 32,
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 937
Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0+ .flags = 0,
Ditto.
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 949
Quoted 12 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +12
-0+ .set_addr = ls1c_nand_set_addr, +}; + +static const struct loongson_nand_data ls2k0500_nand_data = { + .max_id_cycle =6 , + .id_cycle_field =GENMASK (14 ,12 ), + .status_field =GENMASK (23 ,16 ), + .op_scope_field =GENMASK (29 ,16 ), + .hold_cycle =0x4 , + .wait_cycle =0x12 , + .nand_cs =0x0 , + .flags =LOONGSON_NAND_64BIT_DMA ,
Replace LOONGSON_NAND_64BIT_DMA with .dma_bits = 64,
Quoted 22 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +5
-1.set_addr = ls1c_nand_set_addr, };@@ -913,6 +959,10 @@ static const struct of_device_id loongson_nand_match[] = { .compatible = "loongson,ls1c-nand-controller", .data = &ls1c_nand_data, }, + { + .compatible = "loongson,ls2k0500-nand-controller", + .data = &ls2k0500_nand_data, + }, {/* sentinel */ } };MODULE_DEVICE_TABLE (of, loongson_nand_match);@@ -929,5 +979,6 @@ static struct platform_driver loongson_nand_driver = {module_platform_driver (loongson_nand_driver);MODULE_AUTHOR ("Keguang Zhang <[email protected]>" ); +MODULE_AUTHOR ("Binbin Zhou <[email protected]>" );MODULE_DESCRIPTION ("Loongson NAND Controller Driver" );MODULE_LICENSE ("GPL" ); --
Quoted 2 lines
2.47.3
--
Best regards,
Keguang Zhang
Re: [PATCH v2 6/8] mtd: rawnand: loongson: Add Loongson-2K0500 NAND controller support
Hi Keguang:
Thanks for your reply.
Quoted 119 lines · Keguang Zhang
Quoted 73 lines · Binbin Zhou
The Loongson-2K0500 NAND controller is similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum page size of 8KB, and it supports up to 4 chip selects and 4 RDY signals.
Its DMA controller is defaulted to APBDMA0.
Signed-off-by Binbin Zhou <[email protected]>--- drivers/mtd/nand/raw/Kconfig | 2 +- .../mtd/nand/raw/loongson-nand-controller.c | 55 ++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-)drivers/mtd/nand/raw/Kconfig +1
-1@@ -464,7 +464,7 @@ config MTD_NAND_NUVOTON_MA35 config MTD_NAND_LOONGSON tristate "Loongson NAND controller" - depends on LOONGSON1_APB_DMA || COMPILE_TEST + depends on LOONGSON1_APB_DMA || LOONGSON2_APB_DMA || COMPILE_TEST select REGMAP_MMIO help Enables support for NAND controller on Loongson family chips.drivers/mtd/nand/raw/loongson-nand-controller.c +19
-0@@ -3,6 +3,7 @@* NAND Controller Driver for Loongson family chips * * Copyright (C) 2015-2025 Keguang Zhang <[email protected]> +* Copyright (C) 2025 Binbin Zhou <[email protected]> */ #include <linux/kernel.h> @@ -26,6 +27,7 @@#define LOONGSON_NAND_IDH_STATUS 0x14#define LOONGSON_NAND_PARAM 0x18#define LOONGSON_NAND_OP_NUM 0x1c +#define LOONGSON_NAND_CS_RDY_MAP 0x20/* Bitfields of nand command register */ #define LOONGSON_NAND_CMD_OP_DONE BIT(10)@@ -40,6 +42,23 @@#define LOONGSON_NAND_CMD_READ BIT(1)#define LOONGSON_NAND_CMD_VALID BIT(0) +/* Bitfields of nand cs/rdy map register */ +#define LOONGSON_NAND_MAP_CS1_SEL GENMASK(11, 8) +#define LOONGSON_NAND_MAP_RDY1_SEL GENMASK(15, 12) +#define LOONGSON_NAND_MAP_CS2_SEL GENMASK(19, 16) +#define LOONGSON_NAND_MAP_RDY2_SEL GENMASK(23, 20) +#define LOONGSON_NAND_MAP_CS3_SEL GENMASK(27, 24) +#define LOONGSON_NAND_MAP_RDY3_SEL GENMASK(31, 28) + +#define LOONGSON_NAND_CS_SEL0 BIT(0) +#define LOONGSON_NAND_CS_SEL1 BIT(1) +#define LOONGSON_NAND_CS_SEL2 BIT(2) +#define LOONGSON_NAND_CS_SEL3 BIT(3) +#define LOONGSON_NAND_CS_RDY0 BIT(0) +#define LOONGSON_NAND_CS_RDY1 BIT(1) +#define LOONGSON_NAND_CS_RDY2 BIT(2) +#define LOONGSON_NAND_CS_RDY3 BIT(3) +/* Bitfields of nand timing register */ #define LOONGSON_NAND_WAIT_CYCLE_MASK GENMASK(7, 0)#define LOONGSON_NAND_HOLD_CYCLE_MASK GENMASK(15, 8)drivers/mtd/nand/raw/loongson-nand-controller.c line 75
Quoted 4 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0@@ -53,6 +72,8 @@#define LOONGSON_NAND_READ_ID_SLEEP_US 1000#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000 +#define LOONGSON_NAND_64BIT_DMA BIT(0)It's strongly suggested to replace this flag with a
dma_bitsfield inloongson_nand_host.
Please see the comments below.drivers/mtd/nand/raw/loongson-nand-controller.c struct loongson_nand_data { · line 106
Quoted 8 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0+#define BITS_PER_WORD (4 * BITS_PER_BYTE)struct loongson_nand_host ;@@ -83,6 +104,7 @@ struct loongson_nand_data {unsigned int hold_cycle;unsigned int wait_cycle;unsigned int nand_cs;Add unsigned int
dma_bits;Quoted 14 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +2
-1+unsigned int flags;void (*set_addr)(struct loongson_nand_host *host,struct loongson_nand_op *op); };@@ -751,7 +773,7 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)struct device *dev = host->dev;struct dma_chan *chan;struct dma_slave_config cfg = {}; -int ret; +int ret, val; host->regmap =devm_regmap_init_mmio (dev, host->reg_base, &loongson_nand_regmap_config);if (IS_ERR (host->regmap))drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 788
Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +3
-0@@ -761,6 +783,9 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)regmap_update_bits (host->regmap,LOONGSON_NAND_PARAM , host->data->id_cycle_field, host->data->max_id_cycle <<__ffs (host->data->id_cycle_field)); +if (host->data->flags &LOONGSON_NAND_64BIT_DMA ) +dma_set_mask_and_coherent (dev,DMA_BIT_MASK (64 )); +Sorry, all platforms should call
dma_set_mask_and_coherent(), including Loongson-1, which I missed earlier.
ret = dma_set_mask_and_coherent(dev,
Quoted 4 lines
DMA_BIT_MASK(host->data->dma_bits));
if (ret)
return dev_err_probe(dev, ret, "failed to set DMA mask\n");OK, if it is also required by Loongson-1, I will refactor this part. In addition, I will address all of the following comments in the V4 patchset, as the V3 patchset[1] has already been submitted.
[1]: https://lore.kernel.org/all/[email protected]/
You are welcome to continue to comment on that patchset as well.
Quoted 92 lines
Quoted 6 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0
-0chan =dma_request_chan (dev,"rxtx" );if (IS_ERR (chan))return dev_err_probe (dev,PTR_ERR (chan),"failed to request DMA channel\n" );@@ -776,7 +801,14 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)init_completion (&host->dma_complete);drivers/mtd/nand/raw/loongson-nand-controller.c static int loongson_nand_controller_init(struct loongson_nand_host *host) · line 811
Quoted 10 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +8
-1-return 0 ; + val =FIELD_PREP (LOONGSON_NAND_MAP_CS1_SEL ,LOONGSON_NAND_CS_SEL1 ) + |FIELD_PREP (LOONGSON_NAND_MAP_RDY1_SEL ,LOONGSON_NAND_CS_RDY1 ) + |FIELD_PREP (LOONGSON_NAND_MAP_CS2_SEL ,LOONGSON_NAND_CS_SEL2 ) + |FIELD_PREP (LOONGSON_NAND_MAP_RDY2_SEL ,LOONGSON_NAND_CS_RDY2 ) + |FIELD_PREP (LOONGSON_NAND_MAP_CS3_SEL ,LOONGSON_NAND_CS_SEL3 ) + |FIELD_PREP (LOONGSON_NAND_MAP_RDY3_SEL ,LOONGSON_NAND_CS_RDY3 ); + +return regmap_write (host->regmap,LOONGSON_NAND_CS_RDY_MAP , val);Chip selects should be set before requesting the DMA channel.
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 924
Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0
-0}static int loongson_nand_chip_init (struct loongson_nand_host *host)@@ -890,6 +922,7 @@ static const struct loongson_nand_data ls1b_nand_data = { .hold_cycle = 0x2, .wait_cycle = 0xc, .nand_cs = 0x0,Add .dma_bits = 32,
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1b_nand_data = { · line 925
Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0+ .flags = 0,The assignment
.flags = 0x0is redundant and can be removed.drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 936
Quoted 7 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +0
-0.set_addr = ls1b_nand_set_addr, };@@ -901,6 +934,19 @@ static const struct loongson_nand_data ls1c_nand_data = { .hold_cycle = 0x2, .wait_cycle = 0xc, .nand_cs = 0x0,Add .dma_bits = 32,
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 937
Quoted 1 line
drivers/mtd/nand/raw/loongson-nand-controller.c +1
-0+ .flags = 0,Ditto.
drivers/mtd/nand/raw/loongson-nand-controller.c static const struct loongson_nand_data ls1c_nand_data = { · line 949
Quoted 12 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +12
-0+ .set_addr = ls1c_nand_set_addr, +}; + +static const struct loongson_nand_data ls2k0500_nand_data = { + .max_id_cycle =6 , + .id_cycle_field =GENMASK (14 ,12 ), + .status_field =GENMASK (23 ,16 ), + .op_scope_field =GENMASK (29 ,16 ), + .hold_cycle =0x4 , + .wait_cycle =0x12 , + .nand_cs =0x0 , + .flags =LOONGSON_NAND_64BIT_DMA ,Replace
LOONGSON_NAND_64BIT_DMAwith .dma_bits = 64,Quoted 22 lines
drivers/mtd/nand/raw/loongson-nand-controller.c +5
-1.set_addr = ls1c_nand_set_addr, };@@ -913,6 +959,10 @@ static const struct of_device_id loongson_nand_match[] = { .compatible = "loongson,ls1c-nand-controller", .data = &ls1c_nand_data, }, + { + .compatible = "loongson,ls2k0500-nand-controller", + .data = &ls2k0500_nand_data, + }, {/* sentinel */ } };MODULE_DEVICE_TABLE (of, loongson_nand_match);@@ -929,5 +979,6 @@ static struct platform_driver loongson_nand_driver = {module_platform_driver (loongson_nand_driver);MODULE_AUTHOR ("Keguang Zhang <[email protected]>" ); +MODULE_AUTHOR ("Binbin Zhou <[email protected]>" );MODULE_DESCRIPTION ("Loongson NAND Controller Driver" );MODULE_LICENSE ("GPL" ); --Quoted 2 lines
2.47.3
--
Best regards,Keguang Zhang
Signature · 2 lines
Thanks. Binbin
PATCH v2 7/8 dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller
In reply to Binbin ZhouAdd new compatible for the Loongson-2K NAND controller used for Loongson-2K1000 SoC.
--- .../mtd/loongson,ls1b-nand-controller.yaml | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/mtd/loongson,ls1b-nand-controller.yaml +49 -1
@@ -26,18 +26,22 @@ properties: - loongson,ls1b-nand-controller - loongson,ls1c-nand-controller - loongson,ls2k0500-nand-controller + - loongson,ls2k1000-nand-controller - items: - enum: - loongson,ls1a-nand-controller - const: loongson,ls1b-nand-controller reg: - maxItems: 2 + minItems: 2 + maxItems: 3 reg-names: + minItems: 2 items: - const: nand - const: nand-dma + - const: dma-config dmas: maxItems: 1
@@ -54,6 +58,27 @@ required: unevaluatedProperties: false +if: + properties: + compatible: + contains: + enum: + - loongson,ls2k1000-nand-controller + +then: + properties: + reg: + minItems: 3 + reg-names: + minItems: 3 + +else: + properties: + reg: + maxItems: 2 + reg-names: + maxItems: 2 + examples: - | nand-controller@1fe78000 {
@@ -72,3 +97,26 @@ examples: nand-ecc-algo = "hamming"; }; }; + + - | + nand-controller@1fe26000 { + compatible = "loongson,ls2k1000-nand-controller"; + reg = <0x1fe26000 0x24>, + <0x1fe26040 0x4>, + <0x1fe00438 0x8>; + reg-names = "nand", "nand-dma", "dma-config"; + dmas = <&apbdma0 0>; + dma-names = "rxtx"; + + #address-cells = <1>; + #size-cells = <0>; + + nand@0 { + reg = <0>; + label = "ls2k1000-nand"; + nand-use-soft-ecc-engine; + nand-ecc-algo = "bch"; + nand-ecc-strength = <8>; + nand-ecc-step-size = <512>; + }; + };
Signature · 1 line
2.47.3
Re: [PATCH v2 7/8] dt-bindings: mtd: loongson,ls1b-nand-controller: Document the Loongson-2K1000 NAND controller
Quoted 8 lines · Binbin Zhou
Add new compatible for the Loongson-2K NAND controller used for Loongson-2K1000 SoC.
Signed-off-by Binbin Zhou <[email protected]>--- .../mtd/loongson,ls1b-nand-controller.yaml | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-)
PATCH v2 8/8 mtd: rawnand: loongson: Add Loongson-2K1000 NAND controller support
In reply to Binbin ZhouThe Loongson-2K1000 NAND controller is also similar to the Loongson-1C.
It supports a maximum capacity of 16GB FLASH per chip with a maximum page size of 8KB, and it supports up to 4 chip selects and 4 RDY signals.
The key difference from the Loongson-2K0500 is that it requires explicit configuration of the DMA control route. Typically, it is configured as APBDMA0.
--- .../mtd/nand/raw/loongson-nand-controller.c | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+)
drivers/mtd/nand/raw/loongson-nand-controller.c +48 -0
@@ -73,9 +73,18 @@#define LOONGSON_NAND_READ_ID_TIMEOUT_US 5000#define LOONGSON_NAND_64BIT_DMA BIT(0) +#define LOONGSON_NAND_DMA_CONFIG BIT(1)#define BITS_PER_WORD (4 * BITS_PER_BYTE) +/* Loongson-2K1000 NAND DMA routing register */ +#define LS2K1000_NAND_DMA_MASK GENMASK(2, 0) +#define LS2K1000_DMA0_CONF 0x0 +#define LS2K1000_DMA1_CONF 0x1 +#define LS2K1000_DMA2_CONF 0x2 +#define LS2K1000_DMA3_CONF 0x3 +#define LS2K1000_DMA4_CONF 0x4 +struct loongson_nand_host ;struct loongson_nand_op {
@@ -768,6 +777,23 @@ static void loongson_nand_controller_cleanup(struct loongson_nand_host *host)dma_release_channel (host->dma_chan); } +static int ls2k1000_nand_apbdma_config (struct device *dev) +{ +struct platform_device *pdev =to_platform_device (dev); +void __iomem *regs; +int val; + + regs =devm_platform_ioremap_resource (pdev,2 ); +if (IS_ERR (regs)) +return PTR_ERR (regs); + + val =readl (regs); + val |=FIELD_PREP (LS2K1000_NAND_DMA_MASK ,LS2K1000_DMA0_CONF ); +writel (val, regs); + +return 0 ; +} +static int loongson_nand_controller_init (struct loongson_nand_host *host) {struct device *dev = host->dev;
@@ -786,6 +812,12 @@ static int loongson_nand_controller_init(struct loongson_nand_host *host)if (host->data->flags &LOONGSON_NAND_64BIT_DMA )dma_set_mask_and_coherent (dev,DMA_BIT_MASK (64 )); +if (host->data->flags &LOONGSON_NAND_DMA_CONFIG ) { + ret =ls2k1000_nand_apbdma_config (dev); +if (ret) +return ret; + } + chan =dma_request_chan (dev,"rxtx" );if (IS_ERR (chan))return dev_err_probe (dev,PTR_ERR (chan),"failed to request DMA channel\n" );
@@ -950,6 +982,18 @@ static const struct loongson_nand_data ls2k0500_nand_data = { .set_addr = ls1c_nand_set_addr, }; +static const struct loongson_nand_data ls2k1000_nand_data = { + .max_id_cycle =6 , + .id_cycle_field =GENMASK (14 ,12 ), + .status_field =GENMASK (23 ,16 ), + .op_scope_field =GENMASK (29 ,16 ), + .hold_cycle =0x4 , + .wait_cycle =0x12 , + .nand_cs =0x2 , + .flags =LOONGSON_NAND_64BIT_DMA |LOONGSON_NAND_DMA_CONFIG , + .set_addr = ls1c_nand_set_addr, +}; +static const struct of_device_id loongson_nand_match[] = { { .compatible ="loongson,ls1b-nand-controller" ,
@@ -963,6 +1007,10 @@ static const struct of_device_id loongson_nand_match[] = { .compatible = "loongson,ls2k0500-nand-controller", .data = &ls2k0500_nand_data, }, + { + .compatible = "loongson,ls2k1000-nand-controller", + .data = &ls2k1000_nand_data, + }, {/* sentinel */ } };MODULE_DEVICE_TABLE (of, loongson_nand_match);
Signature · 1 line
2.47.3