xref: /linux/drivers/mtd/nand/spi/dosilicon.c (revision 1b49e363252632d0493546511a41a65ed1a6fbbb)
1*a75a1decSAhmed Naseef // SPDX-License-Identifier: GPL-2.0
2*a75a1decSAhmed Naseef /*
3*a75a1decSAhmed Naseef  * Author: Ahmed Naseef <naseefkm@gmail.com>
4*a75a1decSAhmed Naseef  */
5*a75a1decSAhmed Naseef 
6*a75a1decSAhmed Naseef #include <linux/device.h>
7*a75a1decSAhmed Naseef #include <linux/kernel.h>
8*a75a1decSAhmed Naseef #include <linux/mtd/spinand.h>
9*a75a1decSAhmed Naseef 
10*a75a1decSAhmed Naseef #define SPINAND_MFR_DOSILICON        0xE5
11*a75a1decSAhmed Naseef 
12*a75a1decSAhmed Naseef static SPINAND_OP_VARIANTS(read_cache_variants,
13*a75a1decSAhmed Naseef 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
14*a75a1decSAhmed Naseef 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
15*a75a1decSAhmed Naseef 		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
16*a75a1decSAhmed Naseef 		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));
17*a75a1decSAhmed Naseef 
18*a75a1decSAhmed Naseef static SPINAND_OP_VARIANTS(write_cache_variants,
19*a75a1decSAhmed Naseef 		SPINAND_PROG_LOAD_1S_1S_4S_OP(true, 0, NULL, 0),
20*a75a1decSAhmed Naseef 		SPINAND_PROG_LOAD_1S_1S_1S_OP(true, 0, NULL, 0));
21*a75a1decSAhmed Naseef 
22*a75a1decSAhmed Naseef static SPINAND_OP_VARIANTS(update_cache_variants,
23*a75a1decSAhmed Naseef 		SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0),
24*a75a1decSAhmed Naseef 		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));
25*a75a1decSAhmed Naseef 
26*a75a1decSAhmed Naseef static int ds35xx_ooblayout_ecc(struct mtd_info *mtd, int section,
27*a75a1decSAhmed Naseef 				struct mtd_oob_region *region)
28*a75a1decSAhmed Naseef {
29*a75a1decSAhmed Naseef 	if (section > 3)
30*a75a1decSAhmed Naseef 		return -ERANGE;
31*a75a1decSAhmed Naseef 
32*a75a1decSAhmed Naseef 	region->offset = 8 + (section * 16);
33*a75a1decSAhmed Naseef 	region->length = 8;
34*a75a1decSAhmed Naseef 
35*a75a1decSAhmed Naseef 	return 0;
36*a75a1decSAhmed Naseef }
37*a75a1decSAhmed Naseef 
38*a75a1decSAhmed Naseef static int ds35xx_ooblayout_free(struct mtd_info *mtd, int section,
39*a75a1decSAhmed Naseef 				 struct mtd_oob_region *region)
40*a75a1decSAhmed Naseef {
41*a75a1decSAhmed Naseef 	if (section > 3)
42*a75a1decSAhmed Naseef 		return -ERANGE;
43*a75a1decSAhmed Naseef 
44*a75a1decSAhmed Naseef 	if (section == 0) {
45*a75a1decSAhmed Naseef 		/* reserve 2 bytes for the BBM */
46*a75a1decSAhmed Naseef 		region->offset = 2;
47*a75a1decSAhmed Naseef 		region->length = 6;
48*a75a1decSAhmed Naseef 	} else {
49*a75a1decSAhmed Naseef 		region->offset = section * 16;
50*a75a1decSAhmed Naseef 		region->length = 8;
51*a75a1decSAhmed Naseef 	}
52*a75a1decSAhmed Naseef 
53*a75a1decSAhmed Naseef 	return 0;
54*a75a1decSAhmed Naseef }
55*a75a1decSAhmed Naseef 
56*a75a1decSAhmed Naseef static const struct mtd_ooblayout_ops ds35xx_ooblayout = {
57*a75a1decSAhmed Naseef 	.ecc = ds35xx_ooblayout_ecc,
58*a75a1decSAhmed Naseef 	.free = ds35xx_ooblayout_free,
59*a75a1decSAhmed Naseef };
60*a75a1decSAhmed Naseef 
61*a75a1decSAhmed Naseef static const struct spinand_info dosilicon_spinand_table[] = {
62*a75a1decSAhmed Naseef 	SPINAND_INFO("DS35Q1GA",
63*a75a1decSAhmed Naseef 		SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x71),
64*a75a1decSAhmed Naseef 		NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
65*a75a1decSAhmed Naseef 		NAND_ECCREQ(4, 512),
66*a75a1decSAhmed Naseef 		SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
67*a75a1decSAhmed Naseef 					 &write_cache_variants,
68*a75a1decSAhmed Naseef 					 &update_cache_variants),
69*a75a1decSAhmed Naseef 		SPINAND_HAS_QE_BIT,
70*a75a1decSAhmed Naseef 		SPINAND_ECCINFO(&ds35xx_ooblayout, NULL)),
71*a75a1decSAhmed Naseef 	SPINAND_INFO("DS35M1GA",
72*a75a1decSAhmed Naseef 		SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x21),
73*a75a1decSAhmed Naseef 		NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
74*a75a1decSAhmed Naseef 		NAND_ECCREQ(4, 512),
75*a75a1decSAhmed Naseef 		SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
76*a75a1decSAhmed Naseef 					 &write_cache_variants,
77*a75a1decSAhmed Naseef 					 &update_cache_variants),
78*a75a1decSAhmed Naseef 		SPINAND_HAS_QE_BIT,
79*a75a1decSAhmed Naseef 		SPINAND_ECCINFO(&ds35xx_ooblayout, NULL)),
80*a75a1decSAhmed Naseef };
81*a75a1decSAhmed Naseef 
82*a75a1decSAhmed Naseef static const struct spinand_manufacturer_ops dosilicon_spinand_manuf_ops = {
83*a75a1decSAhmed Naseef };
84*a75a1decSAhmed Naseef 
85*a75a1decSAhmed Naseef const struct spinand_manufacturer dosilicon_spinand_manufacturer = {
86*a75a1decSAhmed Naseef 	.id = SPINAND_MFR_DOSILICON,
87*a75a1decSAhmed Naseef 	.name = "Dosilicon",
88*a75a1decSAhmed Naseef 	.chips = dosilicon_spinand_table,
89*a75a1decSAhmed Naseef 	.nchips = ARRAY_SIZE(dosilicon_spinand_table),
90*a75a1decSAhmed Naseef 	.ops = &dosilicon_spinand_manuf_ops,
91*a75a1decSAhmed Naseef };
92