2 * (C) Copyright 2008 Semihalf
4 * Written by: Piotr Ziecik <kosmo@semihalf.com>
6 * See file CREDITS for list of people who contributed to this
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 #include <asm/errno.h>
30 #include <linux/mtd/mtd.h>
32 extern flash_info_t flash_info
[];
34 static struct mtd_info cfi_mtd_info
[CONFIG_SYS_MAX_FLASH_BANKS
];
35 static char cfi_mtd_names
[CONFIG_SYS_MAX_FLASH_BANKS
][16];
37 static int cfi_mtd_erase(struct mtd_info
*mtd
, struct erase_info
*instr
)
39 flash_info_t
*fi
= mtd
->priv
;
40 size_t a_start
= fi
->start
[0] + instr
->addr
;
41 size_t a_end
= a_start
+ instr
->len
;
46 for (sect
= 0; sect
< fi
->sector_count
- 1; sect
++) {
47 if (a_start
== fi
->start
[sect
])
50 if (a_end
== fi
->start
[sect
+ 1]) {
56 if (s_first
>= 0 && s_first
<= s_last
) {
57 instr
->state
= MTD_ERASING
;
60 error
= flash_erase(fi
, s_first
, s_last
);
64 instr
->state
= MTD_ERASE_FAILED
;
68 instr
->state
= MTD_ERASE_DONE
;
69 mtd_erase_callback(instr
);
76 static int cfi_mtd_read(struct mtd_info
*mtd
, loff_t from
, size_t len
,
77 size_t *retlen
, u_char
*buf
)
79 flash_info_t
*fi
= mtd
->priv
;
80 u_char
*f
= (u_char
*)(fi
->start
[0]) + from
;
88 static int cfi_mtd_write(struct mtd_info
*mtd
, loff_t to
, size_t len
,
89 size_t *retlen
, const u_char
*buf
)
91 flash_info_t
*fi
= mtd
->priv
;
92 u_long t
= fi
->start
[0] + to
;
96 error
= write_buff(fi
, (u_char
*)buf
, t
, len
);
107 static void cfi_mtd_sync(struct mtd_info
*mtd
)
110 * This function should wait until all pending operations
111 * finish. However this driver is fully synchronous, so
112 * this function returns immediately
116 static int cfi_mtd_lock(struct mtd_info
*mtd
, loff_t ofs
, size_t len
)
118 flash_info_t
*fi
= mtd
->priv
;
120 flash_set_verbose(0);
121 flash_protect(FLAG_PROTECT_SET
, fi
->start
[0] + ofs
,
122 fi
->start
[0] + ofs
+ len
- 1, fi
);
123 flash_set_verbose(1);
128 static int cfi_mtd_unlock(struct mtd_info
*mtd
, loff_t ofs
, size_t len
)
130 flash_info_t
*fi
= mtd
->priv
;
132 flash_set_verbose(0);
133 flash_protect(FLAG_PROTECT_CLEAR
, fi
->start
[0] + ofs
,
134 fi
->start
[0] + ofs
+ len
- 1, fi
);
135 flash_set_verbose(1);
140 static int cfi_mtd_set_erasesize(struct mtd_info
*mtd
, flash_info_t
*fi
)
145 for (sect
= 0; sect
< fi
->sector_count
; sect
++) {
147 sect_size
= flash_sector_size(fi
, sect
);
151 if (sect_size
!= flash_sector_size(fi
, sect
)) {
158 puts("cfi-mtd: devices with multiple sector sizes are"
163 mtd
->erasesize
= sect_size
;
168 int cfi_mtd_init(void)
170 struct mtd_info
*mtd
;
174 for (i
= 0; i
< CONFIG_SYS_MAX_FLASH_BANKS
; i
++) {
176 mtd
= &cfi_mtd_info
[i
];
178 memset(mtd
, 0, sizeof(struct mtd_info
));
180 error
= cfi_mtd_set_erasesize(mtd
, fi
);
184 sprintf(cfi_mtd_names
[i
], "nor%d", i
);
185 mtd
->name
= cfi_mtd_names
[i
];
186 mtd
->type
= MTD_NORFLASH
;
187 mtd
->flags
= MTD_CAP_NORFLASH
;
188 mtd
->size
= fi
->size
;
191 mtd
->erase
= cfi_mtd_erase
;
192 mtd
->read
= cfi_mtd_read
;
193 mtd
->write
= cfi_mtd_write
;
194 mtd
->sync
= cfi_mtd_sync
;
195 mtd
->lock
= cfi_mtd_lock
;
196 mtd
->unlock
= cfi_mtd_unlock
;
199 if (add_mtd_device(mtd
))