1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2017 Free Electrons
4  * Copyright (C) 2017 NextThing Co
5  *
6  * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
7  */
8 
9 #include "internals.h"
10 
11 /*
12  * Macronix AC series does not support using SET/GET_FEATURES to change
13  * the timings unlike what is declared in the parameter page. Unflag
14  * this feature to avoid unnecessary downturns.
15  */
16 static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
17 {
18 	unsigned int i;
19 	static const char * const broken_get_timings[] = {
20 		"MX30LF1G18AC",
21 		"MX30LF1G28AC",
22 		"MX30LF2G18AC",
23 		"MX30LF2G28AC",
24 		"MX30LF4G18AC",
25 		"MX30LF4G28AC",
26 		"MX60LF8G18AC",
27 		"MX30UF1G18AC",
28 		"MX30UF1G16AC",
29 		"MX30UF2G18AC",
30 		"MX30UF2G16AC",
31 		"MX30UF4G18AC",
32 		"MX30UF4G16AC",
33 		"MX30UF4G28AC",
34 	};
35 
36 	if (!chip->parameters.supports_set_get_features)
37 		return;
38 
39 	for (i = 0; i < ARRAY_SIZE(broken_get_timings); i++) {
40 		if (!strcmp(broken_get_timings[i], chip->parameters.model))
41 			break;
42 	}
43 
44 	if (i == ARRAY_SIZE(broken_get_timings))
45 		return;
46 
47 	bitmap_clear(chip->parameters.get_feature_list,
48 		     ONFI_FEATURE_ADDR_TIMING_MODE, 1);
49 	bitmap_clear(chip->parameters.set_feature_list,
50 		     ONFI_FEATURE_ADDR_TIMING_MODE, 1);
51 }
52 
53 static int macronix_nand_init(struct nand_chip *chip)
54 {
55 	if (nand_is_slc(chip))
56 		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
57 
58 	macronix_nand_fix_broken_get_timings(chip);
59 
60 	return 0;
61 }
62 
63 const struct nand_manufacturer_ops macronix_nand_manuf_ops = {
64 	.init = macronix_nand_init,
65 };
66