1*fc602b4fSAidan MacDonald // SPDX-License-Identifier: GPL-2.0
2*fc602b4fSAidan MacDonald /*
3*fc602b4fSAidan MacDonald * Copyright (C) 2022 Aidan MacDonald
4*fc602b4fSAidan MacDonald *
5*fc602b4fSAidan MacDonald * Author: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
6*fc602b4fSAidan MacDonald */
7*fc602b4fSAidan MacDonald
8*fc602b4fSAidan MacDonald #include <linux/device.h>
9*fc602b4fSAidan MacDonald #include <linux/kernel.h>
10*fc602b4fSAidan MacDonald #include <linux/mtd/spinand.h>
11*fc602b4fSAidan MacDonald
12*fc602b4fSAidan MacDonald
13*fc602b4fSAidan MacDonald #define SPINAND_MFR_ATO 0x9b
14*fc602b4fSAidan MacDonald
15*fc602b4fSAidan MacDonald
16*fc602b4fSAidan MacDonald static SPINAND_OP_VARIANTS(read_cache_variants,
17*fc602b4fSAidan MacDonald SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
18*fc602b4fSAidan MacDonald SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
19*fc602b4fSAidan MacDonald SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
20*fc602b4fSAidan MacDonald
21*fc602b4fSAidan MacDonald static SPINAND_OP_VARIANTS(write_cache_variants,
22*fc602b4fSAidan MacDonald SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
23*fc602b4fSAidan MacDonald SPINAND_PROG_LOAD(true, 0, NULL, 0));
24*fc602b4fSAidan MacDonald
25*fc602b4fSAidan MacDonald static SPINAND_OP_VARIANTS(update_cache_variants,
26*fc602b4fSAidan MacDonald SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
27*fc602b4fSAidan MacDonald SPINAND_PROG_LOAD(false, 0, NULL, 0));
28*fc602b4fSAidan MacDonald
29*fc602b4fSAidan MacDonald
ato25d1ga_ooblayout_ecc(struct mtd_info * mtd,int section,struct mtd_oob_region * region)30*fc602b4fSAidan MacDonald static int ato25d1ga_ooblayout_ecc(struct mtd_info *mtd, int section,
31*fc602b4fSAidan MacDonald struct mtd_oob_region *region)
32*fc602b4fSAidan MacDonald {
33*fc602b4fSAidan MacDonald if (section > 3)
34*fc602b4fSAidan MacDonald return -ERANGE;
35*fc602b4fSAidan MacDonald
36*fc602b4fSAidan MacDonald region->offset = (16 * section) + 8;
37*fc602b4fSAidan MacDonald region->length = 8;
38*fc602b4fSAidan MacDonald return 0;
39*fc602b4fSAidan MacDonald }
40*fc602b4fSAidan MacDonald
ato25d1ga_ooblayout_free(struct mtd_info * mtd,int section,struct mtd_oob_region * region)41*fc602b4fSAidan MacDonald static int ato25d1ga_ooblayout_free(struct mtd_info *mtd, int section,
42*fc602b4fSAidan MacDonald struct mtd_oob_region *region)
43*fc602b4fSAidan MacDonald {
44*fc602b4fSAidan MacDonald if (section > 3)
45*fc602b4fSAidan MacDonald return -ERANGE;
46*fc602b4fSAidan MacDonald
47*fc602b4fSAidan MacDonald if (section) {
48*fc602b4fSAidan MacDonald region->offset = (16 * section);
49*fc602b4fSAidan MacDonald region->length = 8;
50*fc602b4fSAidan MacDonald } else {
51*fc602b4fSAidan MacDonald /* first byte of section 0 is reserved for the BBM */
52*fc602b4fSAidan MacDonald region->offset = 1;
53*fc602b4fSAidan MacDonald region->length = 7;
54*fc602b4fSAidan MacDonald }
55*fc602b4fSAidan MacDonald
56*fc602b4fSAidan MacDonald return 0;
57*fc602b4fSAidan MacDonald }
58*fc602b4fSAidan MacDonald
59*fc602b4fSAidan MacDonald static const struct mtd_ooblayout_ops ato25d1ga_ooblayout = {
60*fc602b4fSAidan MacDonald .ecc = ato25d1ga_ooblayout_ecc,
61*fc602b4fSAidan MacDonald .free = ato25d1ga_ooblayout_free,
62*fc602b4fSAidan MacDonald };
63*fc602b4fSAidan MacDonald
64*fc602b4fSAidan MacDonald
65*fc602b4fSAidan MacDonald static const struct spinand_info ato_spinand_table[] = {
66*fc602b4fSAidan MacDonald SPINAND_INFO("ATO25D1GA",
67*fc602b4fSAidan MacDonald SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x12),
68*fc602b4fSAidan MacDonald NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
69*fc602b4fSAidan MacDonald NAND_ECCREQ(1, 512),
70*fc602b4fSAidan MacDonald SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
71*fc602b4fSAidan MacDonald &write_cache_variants,
72*fc602b4fSAidan MacDonald &update_cache_variants),
73*fc602b4fSAidan MacDonald SPINAND_HAS_QE_BIT,
74*fc602b4fSAidan MacDonald SPINAND_ECCINFO(&ato25d1ga_ooblayout, NULL)),
75*fc602b4fSAidan MacDonald };
76*fc602b4fSAidan MacDonald
77*fc602b4fSAidan MacDonald static const struct spinand_manufacturer_ops ato_spinand_manuf_ops = {
78*fc602b4fSAidan MacDonald };
79*fc602b4fSAidan MacDonald
80*fc602b4fSAidan MacDonald const struct spinand_manufacturer ato_spinand_manufacturer = {
81*fc602b4fSAidan MacDonald .id = SPINAND_MFR_ATO,
82*fc602b4fSAidan MacDonald .name = "ATO",
83*fc602b4fSAidan MacDonald .chips = ato_spinand_table,
84*fc602b4fSAidan MacDonald .nchips = ARRAY_SIZE(ato_spinand_table),
85*fc602b4fSAidan MacDonald .ops = &ato_spinand_manuf_ops,
86*fc602b4fSAidan MacDonald };
87