kernel: mtk_bmt: allow get_mapping_block to return an error
[openwrt/openwrt.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 bmt_desc {
27 struct mtd_info *mtd;
28 unsigned char *bbt_buf;
29 unsigned char *data_buf;
30
31 int (*_read_oob) (struct mtd_info *mtd, loff_t from,
32 struct mtd_oob_ops *ops);
33 int (*_write_oob) (struct mtd_info *mtd, loff_t to,
34 struct mtd_oob_ops *ops);
35 int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
36 int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
37 int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
38
39 const struct mtk_bmt_ops *ops;
40
41 struct bbbt *bbt;
42
43 struct dentry *debugfs_dir;
44
45 u32 table_size;
46 u32 pg_size;
47 u32 blk_size;
48 u16 pg_shift;
49 u16 blk_shift;
50 /* bbt logical address */
51 u16 pool_lba;
52 /* bbt physical address */
53 u16 pool_pba;
54 /* Maximum count of bad blocks that the vendor guaranteed */
55 u16 bb_max;
56 /* Total blocks of the Nand Chip */
57 u16 total_blks;
58 /* The block(n) BMT is located at (bmt_tbl[n]) */
59 u16 bmt_blk_idx;
60 /* How many pages needs to store 'struct bbbt' */
61 u32 bmt_pgs;
62
63 const __be32 *remap_range;
64 int remap_range_len;
65
66 /* to compensate for driver level remapping */
67 u8 oob_offset;
68 };
69
70 extern struct bmt_desc bmtd;
71 extern const struct mtk_bmt_ops mtk_bmt_v2_ops;
72 extern const struct mtk_bmt_ops mtk_bmt_bbt_ops;
73
74 static inline u32 blk_pg(u16 block)
75 {
76 return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift));
77 }
78
79 static inline int
80 bbt_nand_read(u32 page, unsigned char *dat, int dat_len,
81 unsigned char *fdm, int fdm_len)
82 {
83 struct mtd_oob_ops ops = {
84 .mode = MTD_OPS_PLACE_OOB,
85 .ooboffs = bmtd.oob_offset,
86 .oobbuf = fdm,
87 .ooblen = fdm_len,
88 .datbuf = dat,
89 .len = dat_len,
90 };
91
92 return bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops);
93 }
94
95 static inline int bbt_nand_erase(u16 block)
96 {
97 struct mtd_info *mtd = bmtd.mtd;
98 struct erase_info instr = {
99 .addr = (loff_t)block << bmtd.blk_shift,
100 .len = bmtd.blk_size,
101 };
102
103 return bmtd._erase(mtd, &instr);
104 }
105
106 static inline int write_bmt(u16 block, unsigned char *dat)
107 {
108 struct mtd_oob_ops ops = {
109 .mode = MTD_OPS_PLACE_OOB,
110 .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset,
111 .oobbuf = bmtd.ops->sig,
112 .ooblen = bmtd.ops->sig_len,
113 .datbuf = dat,
114 .len = bmtd.bmt_pgs << bmtd.pg_shift,
115 };
116 loff_t addr = (loff_t)block << bmtd.blk_shift;
117
118 return bmtd._write_oob(bmtd.mtd, addr, &ops);
119 }
120
121 int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset);
122 bool mapping_block_in_range(int block, int *start, int *end);
123
124 #endif