Hi Naga,

> > > +/**
> > > + * pl353_nand_read_buf_l - read chip data into buffer
> > > + * @chip:        Pointer to the NAND chip info structure
> > > + * @in:          Pointer to the buffer to store read data
> > > + * @len: Number of bytes to read
> > > + * Return:       Always return zero
> > > + */
> > > +static int pl353_nand_read_buf_l(struct nand_chip *chip,
> > > +                              uint8_t *in,
> > > +                              unsigned int len)
> > > +{
> > > + int i;
> > > + unsigned long *ptr = (unsigned long *)in;
> > > +
> > > + len >>= 2;
> > 
> > Can you please let the compiler optimize things? I don't find this very 
> > readable, I
> > would prefer a division here. And if this division by 4 is related to the 
> > size of *ptr,
> > please use the sizeof() macro. Otherwise please document this value.
> At a time, we are reading 4bytes. Hence >> 2.
> I didn't get your point.
> Are you saying instead of shifting, just use divide by 4?

I do.

> 
> > 
> > > + for (i = 0; i < len; i++)
> > > +         ptr[i] = readl(chip->IO_ADDR_R);
> > 
> > Space
> Ok, I will update it
> > 
> > > + return 0;
> > > +}
> > > +
> > > +static void pl353_nand_write_buf_l(struct nand_chip *chip, const uint8_t
> > *buf,
> > > +                         int len)
> > > +{
> > > + int i;
> > > + unsigned long *ptr = (unsigned long *)buf;
> > > +
> > > + for (i = 0; i < len; i++)
> > > +         writeb(ptr[i], chip->IO_ADDR_W);
> > 
> > Here you use writeb (as opposed to readl previously). Then, I guess you can 
> > also
> > read byte per byte. If so, you can drop both helpers and let the core use 
> > its
> > defaults ones: nand_read/write_buf().
> May be the function name I have written wrongly.
> When using writel, it should be nand_write_buf_l.
> But the thing is, when using exec_op, core is not calling chip->read_byte(), 
> hence I added
> Byte reading.

Well, the point of using ->exec_op() is to forget about these hooks.
->exec_op() will ask you to read one byte if needed. You should forget
about ->read/write_byte/word/buf() hooks and delete them entirely.

> > 
> > Same for the next functions. Plus, if you don't use them inside
> > ->exec_op() implementation, they have to be removed anyway.
> The name of the function should change to buf_l, to do 4byte writes.
> The name is creating confusion.
> > 
> > > +}
> > > +
> > > +/**
> > > + * pl353_nand_write_buf - write buffer to chip
> > > + * @mtd: Pointer to the mtd info structure
> > > + * @buf: Pointer to the buffer to store read data
> > > + * @len: Number of bytes to write
> > > + */
> > > +static void pl353_nand_write_buf(struct mtd_info *mtd, const uint8_t 
> > > *buf,
> > > +                         int len)
> > > +{
> > > + int i;
> > > + struct nand_chip *chip = mtd_to_nand(mtd);
> > > + unsigned long *ptr = (unsigned long *)buf;
> > > +
> > > + len >>= 2;
> > > +
> > > + for (i = 0; i < len; i++)
> > > +         writel(ptr[i], chip->IO_ADDR_W);
> > > +}
> > > +
> > > +/**
> > > + * pl353_nand_read_buf - read chip data into buffer
> > > + * @chip:        Pointer to the NAND chip info structure
> > > + * @in:  Pointer to the buffer to store read data
> > > + * @len: Number of bytes to read
> > > + * Return:       0 on success or error value on failure
> > > + */
> > > +static int pl353_nand_read_buf(struct nand_chip *chip,
> > > +                              uint8_t *in,
> > > +                              unsigned int len)
> > > +{
> > > + int i;
> > > +
> > > + for (i = 0; i < len; i++)
> > > +         in[i] = readb(chip->IO_ADDR_R);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * pl353_nand_calculate_hwecc - Calculate Hardware ECC
> > > + * @mtd: Pointer to the mtd_info structure
> > > + * @data:        Pointer to the page data
> > > + * @ecc_code:    Pointer to the ECC buffer where ECC data needs to be
> > stored
> > 
> > You store ECC in a variable called "code", can you please make it 
> > consistent?
> Miquel, I am not using any variable called "code"

I see "ecc_code", and ECC already stands for "Error Correcting Code".

> > 
> > > + *
> > > + * This function retrieves the Hardware ECC data from the controller
> > > +and returns
> > > + * ECC data back to the MTD subsystem.
> > > + *
> > > + * Return:       0 on success or error value on failure
> > > + */
> > > +static int pl353_nand_calculate_hwecc(struct mtd_info *mtd,
> > > +                         const u8 *data, u8 *ecc_code)
> > > +{
> > > + u32 ecc_value, ecc_status;
> > > + u8 ecc_reg, ecc_byte;
> > > + unsigned long timeout = jiffies + PL353_NAND_ECC_BUSY_TIMEOUT;
> > > + /* Wait till the ECC operation is complete or timeout */
> > > + do {
> > > +         if (pl353_smc_ecc_is_busy())
> > 
> > Where does this function come from?
> The pl353 SMC has memory controller driver and this NAND driver is using 
> those APIs.
> I sent patches to add the memory controller driver for pl353.
> https://www.spinics.net/lists/kernel/msg2748832.html
> https://www.spinics.net/lists/kernel/msg2748834.html
> https://www.spinics.net/lists/kernel/msg2748840.html
> 

ok, please add a reference in your cover letter to the functions that
are not yet merged and you would use in this series.


> > > +
> > > + cmd_phase_addr = (unsigned long __force)xnand->nand_base + (
> > > +                  (((xnand->row_addr_cycles) + (xnand-
> > >col_addr_cycles))
> > > +                  << ADDR_CYCLES_SHIFT) |
> > > +                  (end_cmd_valid << END_CMD_VALID_SHIFT)
> >     |
> > > +                  (COMMAND_PHASE)                                |
> > > +                  (end_cmd << END_CMD_SHIFT)                     |
> > 
> > Please don't align the '|'
> You mean, tabbing? 

Yes

> > 
> > > +                  (start_cmd << START_CMD_SHIFT));
> > > + cmd_addr = (void __iomem * __force)cmd_phase_addr;
> > > +
> > > + /* Get the data phase address */
> > > + data_phase_addr = (unsigned long __force)xnand->nand_base + (
> > > +                   (0x0 << CLEAR_CS_SHIFT)                       |
> > > +                   (0 << END_CMD_VALID_SHIFT)    |
> > > +                   (DATA_PHASE)                                  |
> > > +                   (end_cmd << END_CMD_SHIFT)                    |
> > > +                   (0x0 << ECC_LAST_SHIFT));
> > > +
> > > + chip->IO_ADDR_R = (void __iomem * __force)data_phase_addr;
> > > + chip->IO_ADDR_W = chip->IO_ADDR_R;
> > > + if (chip->options & NAND_BUSWIDTH_16)
> > > +         column >>= 1;
> > 
> >  / 2
> > 
> > > + cmd_data = column;
> > > + if (mtd->writesize > PL353_NAND_ECC_SIZE) {
> > > +         cmd_data |= page << 16;
> > > +         /* Another address cycle for devices > 128MiB */
> > > +         if (chip->chipsize > (128 << 20)) {
> > 
> > Now there is a flag for that in the core, called NAND_ROW_ADDR_3.
> I will check and update.
> > 
> > > +                 pl353_nand_write32(cmd_addr, cmd_data);
> > > +                 cmd_data = (page >> 16);
> > > +         }
> > > + } else {
> > > +         cmd_data |= page << 8;
> > > + }
> > 
> > Space
> Ok, I will update.
> > 
> > > + pl353_nand_write32(cmd_addr, cmd_data); }
> > > +
> > > +/**
> > > + * pl353_nand_read_oob - [REPLACEABLE] the most common OOB data read
> > function
> > > + * @mtd: Pointer to the mtd info structure
> > > + * @chip:        Pointer to the NAND chip info structure
> > > + * @page:        Page number to read
> > > + *
> > > + * Return:       Always return zero
> > > + */
> > > +static int pl353_nand_read_oob(struct mtd_info *mtd, struct nand_chip
> > *chip,
> > > +                     int page)
> > > +{
> > > +
> > > + unsigned long data_phase_addr;
> > > + uint8_t *p;
> > > +
> > > + chip->pagebuf = -1;
> > > + if (mtd->writesize < PL353_NAND_ECC_SIZE)
> > > +         return 0;
> > > +
> > > + pl353_prepare_cmd(mtd, chip, page, mtd->writesize,
> > NAND_CMD_READ0,
> > > +         NAND_CMD_READSTART, 1);
> > 
> > Alignment
> Are you running any script apart from checkpatch?
> Any way I will correct it.

All my comments have been made "manually" without tool but you should
definitively run checkpatch.pl --strict on all your patches before
sending them.


> > > +
> > > + return (status & NAND_STATUS_FAIL) ? -EIO : 0; }
> > > +
> > > +/**
> > > + * pl353_nand_read_page_raw - [Intern] read raw page data without ecc
> > > + * @mtd:         Pointer to the mtd info structure
> > > + * @chip:                Pointer to the NAND chip info structure
> > > + * @buf:         Pointer to the data buffer
> > > + * @oob_required:        Caller requires OOB data read to chip->oob_poi
> > > + * @page:                Page number to read
> > > + *
> > > + * Return:       Always return zero
> > > + */
> > > +static int pl353_nand_read_page_raw(struct mtd_info *mtd,
> > > +                         struct nand_chip *chip,
> > > +                         uint8_t *buf, int oob_required, int page)
> > 
> > Do you really need raw accessors?
> Yes, when using on-die ecc, this function is getting called.
> i.e. nand_micron.c is calling nand_set_features_op, with DATA_OUT_INSTR, and 
> there
> we are using this.

I don't see any link between doing a nad_set_features_op and calling a
raw accessor. It's almost like the ->read_byte() hook, if there is
nothing specific to implement, just forget about it, ->exec_op() is
probably enough.

> > > +/**
> > > + * pl353_nand_select_chip - Select the flash device
> > > + * @mtd: Pointer to the mtd info structure
> > > + * @chip:        Pointer to the NAND chip info structure
> > > + *
> > > + * This function is empty as the NAND controller handles chip select
> > > +line
> > > + * internally based on the chip address passed in command and data phase.
> > > + */
> > > +static void pl353_nand_select_chip(struct mtd_info *mtd, int chip) {
> > > +}
> > > +
> > > +/* NAND framework ->exec_op() hooks and related helpers */ static
> > > +void pl353_nfc_parse_instructions(struct nand_chip *chip,
> > > +                                    const struct nand_subop *subop,
> > > +                                    struct pl353_nfc_op *nfc_op)
> > > +{
> > > + const struct nand_op_instr *instr = NULL;
> > > + unsigned int op_id, offset, naddrs;
> > > + int i;
> > > + const u8 *addrs;
> > > +
> > > + memset(nfc_op, 0, sizeof(struct pl353_nfc_op));
> > > + for (op_id = 0; op_id < subop->ninstrs; op_id++) {
> > > +
> > 
> > What is this for-loop for? I don't get it as you break the switch in every 
> > case?
> I think, breaking switch case only not for loop.

My bad, ok.

> > 
> > > +         nfc_op->len = nand_subop_get_data_len(subop, op_id);
> > > +
> > > +         instr = &subop->instrs[op_id];
> > > +         if (subop->ninstrs == 1)
> > > +                 nfc_op->cmnds[0] = -1;
> > > +         switch (instr->type) {
> > > +         case NAND_OP_CMD_INSTR:
> > > +                 nfc_op->type = NAND_OP_CMD_INSTR;
> > > +                 nfc_op->end_cmd = op_id - 1;
> > > +                 if (op_id)
> > 
> > You should put { } on the if also if the else statement needs braces.
> Ok, but I didn't see any warning from checkpatch.

Maybe with the --strict option?
Otherwise this is clearly stated in the kernel coding style
documentation.


> > > +static const struct nand_op_parser pl353_nfc_op_parser =
> > NAND_OP_PARSER(
> > > + NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false),
> > > +         NAND_OP_PARSER_PAT_ADDR_ELEM(false, 7),
> > > +         NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 8)),
> > > +  NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false),
> > > +         NAND_OP_PARSER_PAT_ADDR_ELEM(false, 7),
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false),
> > > +         NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
> > > + NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false),
> > > +         NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 8)),
> > > +  NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false),
> > > +         NAND_OP_PARSER_PAT_ADDR_ELEM(false, 7),
> > > +         NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
> > > + NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false),
> > > +         NAND_OP_PARSER_PAT_ADDR_ELEM(false, 8),
> > > +         NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, 2048),
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(true),
> > > +         NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)),
> > > + NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false),
> > > +         NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
> > > + NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 2048)),
> > > + NAND_OP_PARSER_PATTERN(
> > > +         pl353_nand_cmd_function,
> > > +         NAND_OP_PARSER_PAT_CMD_ELEM(false)),
> > 
> > I am pretty sure you can factorize all these patterns now. Use the 
> > "optional"
> > parameter for that.
> Can you explain little bit?  I didn't get.

All the patterns refer to the same function. This is fine.
But maybe you can factorize the parents using the "optional" parameter.
For example, if you have
* CMD + ADDR + DATA_IN
* CMD + DATA_IN
Maybe you can just state:
* CMD + [ADDR] + DATA_IN
With "[]" meaning the element is optional.


Thanks for addressing these comments.

Regards,
Miquèl

-- 
Miquel Raynal, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

Reply via email to