[PATCH v2 4/4] mtd: rawnand: brcmnand: exec_op implementation

dregan at mail.com dregan at mail.com
Thu Oct 12 14:28:59 PDT 2023


Hi Miquèl,

>
> Hello,
> 
> dregan at mail.com wrote on Thu, 12 Oct 2023 02:42:37 +0200:
> 

...

> > +
> > +int brcmnand_exec_op_is_status(const struct nand_operation *op)
> > +{
> > +	if ((op->instrs[0].type == NAND_OP_CMD_INSTR) &&
> > +		(op->instrs[0].ctx.cmd.opcode == NAND_CMD_STATUS) &&
> > +		(op->ninstrs > 1) &&
> > +		(op->instrs[1].type == NAND_OP_DATA_IN_INSTR))
> 
> You need to start checking if op->ninstrs == 2, no?

Will fix.

> 
> > +		return 1;
> > +
> > +	return 0;
> > +}
> > +
> > +int brcmnand_exec_op_is_reset(const struct nand_operation *op)
> > +{
> > +	if ((op->instrs[0].type == NAND_OP_CMD_INSTR) &&
> > +		(op->instrs[0].ctx.cmd.opcode == NAND_CMD_RESET))
> 
> Please check ninstrs as well (first).

Will do.

> 
> > +		return 1;
> > +
> > +	return 0;
> > +}
> > +
> > +static int brcmnand_exec_op(struct nand_chip *chip,
> > +			    const struct nand_operation *op,
> > +			    bool check_only)
> > +{
> > +	struct brcmnand_host *host = nand_get_controller_data(chip);
> > +	struct mtd_info *mtd = nand_to_mtd(chip);
> > +	const struct nand_op_instr *instr = &op->instrs[0];
> > +	u8 *status;
> > +	unsigned int i;
> > +	int ret = 0;
> > +
> > +	if (check_only)
> > +		return 0;
> > +
> > +	if (brcmnand_exec_op_is_status(op)) {
> > +		status = op->instrs[1].ctx.data.buf.in;
> > +		*status = brcmnand_status(host);
> > +
> > +		return 0;
> > +	}
> > +
> > +	if (op->deassert_wp)
> > +		brcmnand_wp(mtd, 0);
> > +
> > +	for (i = 0; i < op->ninstrs; i++) {
> > +		instr = &op->instrs[i];
> > +
> > +		if (instr->type == NAND_OP_WAITRDY_INSTR) {
> > +			ret = bcmnand_ctrl_poll_status(host, NAND_CTRL_RDY, NAND_CTRL_RDY, 0);
> 
> Why don't you handle this in brcmnand_exec_instr() ? It would look much
> nicer. Even if this does not involve any additional "cycle" on the NAND
> bus, it still is an instruction of the current operation.

Good idea.

> 
> > +			if (ret)
> > +				break;
> > +		} else { /* otherwise pass to low level implementation */
> > +			ret = brcmnand_exec_instr(host, instr, i == (op->ninstrs - 1));
> 
> What's the point of this i == op->ninstrs - 1 check?
> 

It's to let the controller know we are issuing the last command
in a series of commands. I may need to rework this as to moving
waitrdy into brcmnand_exec_instr


> > +			if (ret)
> > +				break;
> > +		}
> > +	}
> > +
> > +	if (op->deassert_wp)
> > +		brcmnand_wp(mtd, 1);
> > +
> > +	if (brcmnand_exec_op_is_reset(op)) {
> > +		brcmnand_status(host);
> > +		brcmnand_wp(mtd, 1);
> 
> This should be done right after the status check, no?
> 
> Anyway, I'm not sure I understand this. Why do you read the status and
> assert WP?

I read the status to fill the cached status, and reset the WP to
it's default state.

...

> Thanks,
> Miquèl
>

Thanks!

-Dave



More information about the linux-mtd mailing list