kernel: Add support for Winbond w25q128jv SPI NOR flash
[oweals/openwrt.git] / target / linux / ramips / patches-4.14 / 0054-mtd-spi-nor-w25q256-respect-default-mode.patch
1 --- a/drivers/mtd/spi-nor/spi-nor.c
2 +++ b/drivers/mtd/spi-nor/spi-nor.c
3 @@ -142,20 +142,29 @@ static int read_fsr(struct spi_nor *nor)
4   * location. Return the configuration register value.
5   * Returns negative if error occurred.
6   */
7 -static int read_cr(struct spi_nor *nor)
8 +static int _read_cr(struct spi_nor *nor, u8 reg)
9  {
10         int ret;
11         u8 val;
12  
13 -       ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1);
14 +       ret = nor->read_reg(nor, reg, &val, 1);
15         if (ret < 0) {
16 -               dev_err(nor->dev, "error %d reading CR\n", ret);
17 +               dev_err(nor->dev, "error %d reading %s\n", ret,
18 +                       (reg==SPINOR_OP_RDCR)?"CR":"XCR");
19                 return ret;
20         }
21  
22         return val;
23  }
24  
25 +static inline int read_cr(struct spi_nor *nor) {
26 +       return _read_cr(nor, SPINOR_OP_RDCR);
27 +}
28 +
29 +static inline int read_xcr(struct spi_nor *nor) {
30 +       return _read_cr(nor, SPINOR_OP_RDXCR);
31 +}
32 +
33  /*
34   * Write status register 1 byte
35   * Returns negative if error occurred.
36 @@ -2883,9 +2892,16 @@ int spi_nor_scan(struct spi_nor *nor, co
37         } else if (mtd->size > 0x1000000) {
38                 /* enable 4-byte addressing if the device exceeds 16MiB */
39                 nor->addr_width = 4;
40 -               if (info->flags & SPI_NOR_4B_READ_OP)
41 -                       spi_nor_set_4byte_read(nor, info);
42 -               else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
43 +               if (info->flags & SPI_NOR_4B_READ_OP) {
44 +                       if (JEDEC_MFR(info) == SNOR_MFR_WINBOND) {
45 +                               ret = read_xcr(nor);
46 +                               if (!(ret > 0 && (ret & XCR_DEF_4B_ADDR_MODE)))
47 +                                       spi_nor_set_4byte_read(nor, info);
48 +                               else
49 +                                       set_4byte(nor, info, 1);
50 +                       } else
51 +                               spi_nor_set_4byte_read(nor, info);
52 +               } else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
53                          info->flags & SPI_NOR_4B_OPCODES)
54                         spi_nor_set_4byte_opcodes(nor, info);
55                 else
56 --- a/include/linux/mtd/spi-nor.h
57 +++ b/include/linux/mtd/spi-nor.h
58 @@ -103,6 +103,7 @@
59  #define SPINOR_OP_EN4B         0xb7    /* Enter 4-byte mode */
60  #define SPINOR_OP_EX4B         0xe9    /* Exit 4-byte mode */
61  #define SPINOR_OP_WREAR                0xc5    /* Write extended address register */
62 +#define SPINOR_OP_RDXCR                0x15    /* Read extended configuration register */
63  
64  /* Used for Spansion flashes only. */
65  #define SPINOR_OP_BRWR         0x17    /* Bank register write */
66 @@ -135,6 +136,7 @@
67  
68  /* Configuration Register bits. */
69  #define CR_QUAD_EN_SPAN                BIT(1)  /* Spansion Quad I/O */
70 +#define XCR_DEF_4B_ADDR_MODE   BIT(1)  /* Winbond 4B mode default */
71  
72  /* Status Register 2 bits. */
73  #define SR2_QUAD_EN_BIT7       BIT(7)