kernel: mtk-bmt: fix usage of _oob_read
[openwrt/staging/noltari.git] / target / linux / generic / files / drivers / mtd / nand / mtk_bmt.h
1 #ifndef __MTK_BMT_PRIV_H
2 #define __MTK_BMT_PRIV_H
3
4 #include <linux/kernel.h>
5 #include <linux/of.h>
6 #include <linux/mtd/mtd.h>
7 #include <linux/mtd/partitions.h>
8 #include <linux/mtd/mtk_bmt.h>
9 #include <linux/debugfs.h>
10
11 #define MAIN_SIGNATURE_OFFSET 0
12 #define OOB_SIGNATURE_OFFSET 1
13
14 #define BBT_LOG(fmt, ...) pr_debug("[BBT][%s|%d] "fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
15
16 struct mtk_bmt_ops {
17 char *sig;
18 unsigned int sig_len;
19 int (*init)(struct device_node *np);
20 bool (*remap_block)(u16 block, u16 mapped_block, int copy_len);
21 void (*unmap_block)(u16 block);
22 int (*get_mapping_block)(int block);
23 int (*debug)(void *data, u64 val);
24 };
25
26 struct bbbt;
27 struct nmbm_instance;
28
29 struct bmt_desc {
30 struct mtd_info *mtd;
31 unsigned char *bbt_buf;
32 unsigned char *data_buf;
33
34 int (*_read_oob) (struct mtd_info *mtd, loff_t from,
35 struct mtd_oob_ops *ops);
36 int (*_write_oob) (struct mtd_info *mtd, loff_t to,
37 struct mtd_oob_ops *ops);
38 int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
39 int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
40 int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
41
42 const struct mtk_bmt_ops *ops;
43
44 union {
45 struct bbbt *bbt;
46 struct nmbm_instance *ni;
47 };
48
49 struct dentry *debugfs_dir;
50
51 u32 table_size;
52 u32 pg_size;
53 u32 blk_size;
54 u16 pg_shift;
55 u16 blk_shift;
56 /* bbt logical address */
57 u16 pool_lba;
58 /* bbt physical address */
59 u16 pool_pba;
60 /* Maximum count of bad blocks that the vendor guaranteed */
61 u16 bb_max;
62 /* Total blocks of the Nand Chip */
63 u16 total_blks;
64 /* The block(n) BMT is located at (bmt_tbl[n]) */
65 u16 bmt_blk_idx;
66 /* How many pages needs to store 'struct bbbt' */
67 u32 bmt_pgs;
68
69 const __be32 *remap_range;
70 int remap_range_len;
71
72 /* to compensate for driver level remapping */
73 u8 oob_offset;
74 };
75
76 extern struct bmt_desc bmtd;
77 extern const struct mtk_bmt_ops mtk_bmt_v2_ops;
78 extern const struct mtk_bmt_ops mtk_bmt_bbt_ops;
79 extern const struct mtk_bmt_ops mtk_bmt_nmbm_ops;
80
81 static inline u32 blk_pg(u16 block)
82 {
83 return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift));
84 }
85
86 static inline int
87 bbt_nand_read(u32 page, unsigned char *dat, int dat_len,
88 unsigned char *fdm, int fdm_len)
89 {
90 struct mtd_oob_ops ops = {
91 .mode = MTD_OPS_PLACE_OOB,
92 .ooboffs = bmtd.oob_offset,
93 .oobbuf = fdm,
94 .ooblen = fdm_len,
95 .datbuf = dat,
96 .len = dat_len,
97 };
98 int ret;
99
100 ret = bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops);
101 if (ret < 0)
102 return ret;
103 if (ret)
104 pr_info("%s: %d bitflips\n", __func__, ret);
105 return 0;
106 }
107
108 static inline int bbt_nand_erase(u16 block)
109 {
110 struct mtd_info *mtd = bmtd.mtd;
111 struct erase_info instr = {
112 .addr = (loff_t)block << bmtd.blk_shift,
113 .len = bmtd.blk_size,
114 };
115
116 return bmtd._erase(mtd, &instr);
117 }
118
119 static inline int write_bmt(u16 block, unsigned char *dat)
120 {
121 struct mtd_oob_ops ops = {
122 .mode = MTD_OPS_PLACE_OOB,
123 .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset,
124 .oobbuf = bmtd.ops->sig,
125 .ooblen = bmtd.ops->sig_len,
126 .datbuf = dat,
127 .len = bmtd.bmt_pgs << bmtd.pg_shift,
128 };
129 loff_t addr = (loff_t)block << bmtd.blk_shift;
130
131 return bmtd._write_oob(bmtd.mtd, addr, &ops);
132 }
133
134 int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset);
135 bool mapping_block_in_range(int block, int *start, int *end);
136
137 #endif