44 * Copyright (C) 2014, Freescale Semiconductor, Inc.
55 */
66
7+ #include <linux/device.h>
78#include <linux/mtd/spi-nor.h>
89
910#include "core.h"
1011
1112/* flash_info mfr_flag. Used to clear sticky prorietary SR bits. */
1213#define USE_CLSR BIT(0)
14+ #define USE_CLPEF BIT(1)
1315
1416#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
17+ #define SPINOR_OP_CLPEF 0x82 /* Clear program/erase failure flags */
1518#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */
1619#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */
1720#define SPINOR_REG_CYPRESS_VREG 0x00800000
5760 SPI_MEM_OP_DUMMY(ndummy, 0), \
5861 SPI_MEM_OP_DATA_IN(1, buf, 0))
5962
60- #define SPANSION_CLSR_OP \
61- SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR , 0), \
63+ #define SPANSION_OP ( opcode ) \
64+ SPI_MEM_OP(SPI_MEM_OP_CMD(opcode , 0), \
6265 SPI_MEM_OP_NO_ADDR, \
6366 SPI_MEM_OP_NO_DUMMY, \
6467 SPI_MEM_OP_NO_DATA)
6568
69+ /**
70+ * struct spansion_nor_params - Spansion private parameters.
71+ * @clsr: Clear Status Register or Clear Program and Erase Failure Flag
72+ * opcode.
73+ */
74+ struct spansion_nor_params {
75+ u8 clsr ;
76+ };
77+
6678/**
6779 * spansion_nor_clear_sr() - Clear the Status Register.
6880 * @nor: pointer to 'struct spi_nor'.
6981 */
7082static void spansion_nor_clear_sr (struct spi_nor * nor )
7183{
84+ const struct spansion_nor_params * priv_params = nor -> params -> priv ;
7285 int ret ;
7386
7487 if (nor -> spimem ) {
75- struct spi_mem_op op = SPANSION_CLSR_OP ;
88+ struct spi_mem_op op = SPANSION_OP ( priv_params -> clsr ) ;
7689
7790 spi_nor_spimem_setup_op (nor , & op , nor -> reg_proto );
7891
@@ -528,9 +541,11 @@ static int s25fs256t_post_sfdp_fixup(struct spi_nor *nor)
528541 return 0 ;
529542}
530543
531- static void s25fs256t_late_init (struct spi_nor * nor )
544+ static int s25fs256t_late_init (struct spi_nor * nor )
532545{
533546 cypress_nor_ecc_init (nor );
547+
548+ return 0 ;
534549}
535550
536551static struct spi_nor_fixups s25fs256t_fixups = {
@@ -586,7 +601,7 @@ static int s25hx_t_post_sfdp_fixup(struct spi_nor *nor)
586601 return cypress_nor_get_page_size (nor );
587602}
588603
589- static void s25hx_t_late_init (struct spi_nor * nor )
604+ static int s25hx_t_late_init (struct spi_nor * nor )
590605{
591606 struct spi_nor_flash_parameter * params = nor -> params ;
592607
@@ -598,6 +613,8 @@ static void s25hx_t_late_init(struct spi_nor *nor)
598613 /* Replace ready() with multi die version */
599614 if (params -> n_dice )
600615 params -> ready = cypress_nor_sr_ready_and_clear ;
616+
617+ return 0 ;
601618}
602619
603620static struct spi_nor_fixups s25hx_t_fixups = {
@@ -659,10 +676,12 @@ static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
659676 return cypress_nor_set_addr_mode_nbytes (nor );
660677}
661678
662- static void s28hx_t_late_init (struct spi_nor * nor )
679+ static int s28hx_t_late_init (struct spi_nor * nor )
663680{
664681 nor -> params -> set_octal_dtr = cypress_nor_set_octal_dtr ;
665682 cypress_nor_ecc_init (nor );
683+
684+ return 0 ;
666685}
667686
668687static const struct spi_nor_fixups s28hx_t_fixups = {
@@ -786,47 +805,54 @@ static const struct flash_info spansion_nor_parts[] = {
786805 FIXUP_FLAGS (SPI_NOR_4B_OPCODES ) },
787806 { "s25fs256t" , INFO6 (0x342b19 , 0x0f0890 , 0 , 0 )
788807 PARSE_SFDP
808+ MFR_FLAGS (USE_CLPEF )
789809 .fixups = & s25fs256t_fixups },
790810 { "s25hl512t" , INFO6 (0x342a1a , 0x0f0390 , 256 * 1024 , 256 )
791811 PARSE_SFDP
792- MFR_FLAGS (USE_CLSR )
812+ MFR_FLAGS (USE_CLPEF )
793813 .fixups = & s25hx_t_fixups },
794814 { "s25hl01gt" , INFO6 (0x342a1b , 0x0f0390 , 256 * 1024 , 512 )
795815 PARSE_SFDP
796- MFR_FLAGS (USE_CLSR )
816+ MFR_FLAGS (USE_CLPEF )
797817 .fixups = & s25hx_t_fixups },
798818 { "s25hl02gt" , INFO6 (0x342a1c , 0x0f0090 , 0 , 0 )
799819 PARSE_SFDP
820+ MFR_FLAGS (USE_CLPEF )
800821 FLAGS (NO_CHIP_ERASE )
801822 .fixups = & s25hx_t_fixups },
802823 { "s25hs512t" , INFO6 (0x342b1a , 0x0f0390 , 256 * 1024 , 256 )
803824 PARSE_SFDP
804- MFR_FLAGS (USE_CLSR )
825+ MFR_FLAGS (USE_CLPEF )
805826 .fixups = & s25hx_t_fixups },
806827 { "s25hs01gt" , INFO6 (0x342b1b , 0x0f0390 , 256 * 1024 , 512 )
807828 PARSE_SFDP
808- MFR_FLAGS (USE_CLSR )
829+ MFR_FLAGS (USE_CLPEF )
809830 .fixups = & s25hx_t_fixups },
810831 { "s25hs02gt" , INFO6 (0x342b1c , 0x0f0090 , 0 , 0 )
811832 PARSE_SFDP
833+ MFR_FLAGS (USE_CLPEF )
812834 FLAGS (NO_CHIP_ERASE )
813835 .fixups = & s25hx_t_fixups },
814836 { "cy15x104q" , INFO6 (0x042cc2 , 0x7f7f7f , 512 * 1024 , 1 )
815837 FLAGS (SPI_NOR_NO_ERASE ) },
816838 { "s28hl512t" , INFO (0x345a1a , 0 , 256 * 1024 , 256 )
817839 PARSE_SFDP
840+ MFR_FLAGS (USE_CLPEF )
818841 .fixups = & s28hx_t_fixups ,
819842 },
820843 { "s28hl01gt" , INFO (0x345a1b , 0 , 256 * 1024 , 512 )
821844 PARSE_SFDP
845+ MFR_FLAGS (USE_CLPEF )
822846 .fixups = & s28hx_t_fixups ,
823847 },
824848 { "s28hs512t" , INFO (0x345b1a , 0 , 256 * 1024 , 256 )
825849 PARSE_SFDP
850+ MFR_FLAGS (USE_CLPEF )
826851 .fixups = & s28hx_t_fixups ,
827852 },
828853 { "s28hs01gt" , INFO (0x345b1b , 0 , 256 * 1024 , 512 )
829854 PARSE_SFDP
855+ MFR_FLAGS (USE_CLPEF )
830856 .fixups = & s28hx_t_fixups ,
831857 },
832858};
@@ -870,17 +896,35 @@ static int spansion_nor_sr_ready_and_clear(struct spi_nor *nor)
870896 return !(nor -> bouncebuf [0 ] & SR_WIP );
871897}
872898
873- static void spansion_nor_late_init (struct spi_nor * nor )
899+ static int spansion_nor_late_init (struct spi_nor * nor )
874900{
875- if (nor -> params -> size > SZ_16M ) {
901+ struct spi_nor_flash_parameter * params = nor -> params ;
902+ struct spansion_nor_params * priv_params ;
903+ u8 mfr_flags = nor -> info -> mfr_flags ;
904+
905+ if (params -> size > SZ_16M ) {
876906 nor -> flags |= SNOR_F_4B_OPCODES ;
877907 /* No small sector erase for 4-byte command set */
878908 nor -> erase_opcode = SPINOR_OP_SE ;
879909 nor -> mtd .erasesize = nor -> info -> sector_size ;
880910 }
881911
882- if (nor -> info -> mfr_flags & USE_CLSR )
883- nor -> params -> ready = spansion_nor_sr_ready_and_clear ;
912+ if (mfr_flags & (USE_CLSR | USE_CLPEF )) {
913+ priv_params = devm_kmalloc (nor -> dev , sizeof (* priv_params ),
914+ GFP_KERNEL );
915+ if (!priv_params )
916+ return - ENOMEM ;
917+
918+ if (mfr_flags & USE_CLSR )
919+ priv_params -> clsr = SPINOR_OP_CLSR ;
920+ else if (mfr_flags & USE_CLPEF )
921+ priv_params -> clsr = SPINOR_OP_CLPEF ;
922+
923+ params -> priv = priv_params ;
924+ params -> ready = spansion_nor_sr_ready_and_clear ;
925+ }
926+
927+ return 0 ;
884928}
885929
886930static const struct spi_nor_fixups spansion_nor_fixups = {
0 commit comments