How to Check E_ERR/P_ERR Status Errors in the Linux MTD SPI Driver – KBA220225

Version 2

    Version: **

     

    Translation - Japanese: Linux MTD SPIドライバでE_ERR/P_ERRステータス エラーを確認する方法– KBA220225- Community Translated (JA)

     

    Question:

    How do I add flash program/erase failure status checking to the Linux SPI MTD SPI Driver?

     

    Answer:

    The Linux master code doesn’t check for program/erase failure of SPI driver. The following steps will add this error-checking feature to the driver

     

    1. Add E_ERR and P_ERR bit field definitions to SPI driver for FL-S and FS-S (in case of FL-L, use Status Register 2 instead of Status Register 1):

    • Open include/linux/mtd/spi-nor.h
    • Find Status Register bits definitions and replace the following:

              #define SR_TB BIT(5) /* Top/Bottom protect */

     

              with:

     

              #define SR_E_ERR BIT(5) /* Erase error occurred */

              #define SR_P_ERR BIT(6) /* Programming error occurred */

    • Find Flash opcodes section and add Clear Status Register opcode

              #define SPINOR_OP_CLSR 0x30 /* Clear status register */

     

    2. Add E_ERR and P_ERR status bit checking to the Status Ready checking subroutine:

    • Open drivers/mtd/spi-nor/spi-nor.c
    • Add clear_sr() subroutine

              /*

              * Clear status register

              * Returns negative if error occurred.

              */

              static inline int clear_sr(struct spi_nor *nor)

              {

                   return nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0);

              }

    • Add a user notification subroutine when erase or program failure happens, for example, user_error_handler()
    • Find static inline int spi_nor_sr_ready(struct spi_nor *nor)
    • Modify the code from:

     

                     int sr = read_sr(nor);

                             if (sr < 0)

                             return sr;

     

                             else

                             return !(sr & SR_WIP);

                             to:

     

                             int sr = read_sr(nor);

                             if (sr < 0)

                                  return sr;

                             else if ((sr & SR_E_ERR) || (sr & SR_P_ERR))

                            {

                                        user_error_handler();

                                        write_enable(nor);

                                        clear_sr(nor);

                            }

                            return !(sr & SR_WIP);