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