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
];
36 static int cfi_mtd_erase(struct mtd_info
*mtd
, struct erase_info
*instr
)
38 flash_info_t
*fi
= mtd
->priv
;
39 size_t a_start
= fi
->start
[0] + instr
->addr
;
40 size_t a_end
= a_start
+ instr
->len
;
45 for (sect
= 0; sect
< fi
->sector_count
- 1; sect
++) {
46 if (a_start
== fi
->start
[sect
])
49 if (a_end
== fi
->start
[sect
+ 1]) {
55 if (s_first
>= 0 && s_first
<= s_last
) {
56 instr
->state
= MTD_ERASING
;
59 error
= flash_erase(fi
, s_first
, s_last
);
63 instr
->state
= MTD_ERASE_FAILED
;
67 instr
->state
= MTD_ERASE_DONE
;
68 mtd_erase_callback(instr
);
75 static int cfi_mtd_read(struct mtd_info
*mtd
, loff_t from
, size_t len
,
76 size_t *retlen
, u_char
*buf
)
78 flash_info_t
*fi
= mtd
->priv
;
79 u_char
*f
= (u_char
*)(fi
->start
[0]) + from
;
87 static int cfi_mtd_write(struct mtd_info
*mtd
, loff_t to
, size_t len
,
88 size_t *retlen
, const u_char
*buf
)
90 flash_info_t
*fi
= mtd
->priv
;
91 u_long t
= fi
->start
[0] + to
;
95 error
= write_buff(fi
, (u_char
*)buf
, t
, len
);
106 static void cfi_mtd_sync(struct mtd_info
*mtd
)
109 * This function should wait until all pending operations
110 * finish. However this driver is fully synchronous, so
111 * this function returns immediately
115 static int cfi_mtd_lock(struct mtd_info
*mtd
, loff_t ofs
, size_t len
)
117 flash_info_t
*fi
= mtd
->priv
;
119 flash_set_verbose(0);
120 flash_protect(FLAG_PROTECT_SET
, fi
->start
[0] + ofs
,
121 fi
->start
[0] + ofs
+ len
- 1, fi
);
122 flash_set_verbose(1);
127 static int cfi_mtd_unlock(struct mtd_info
*mtd
, loff_t ofs
, size_t len
)
129 flash_info_t
*fi
= mtd
->priv
;
131 flash_set_verbose(0);
132 flash_protect(FLAG_PROTECT_CLEAR
, fi
->start
[0] + ofs
,
133 fi
->start
[0] + ofs
+ len
- 1, fi
);
134 flash_set_verbose(1);
139 static int cfi_mtd_set_erasesize(struct mtd_info
*mtd
, flash_info_t
*fi
)
144 for (sect
= 0; sect
< fi
->sector_count
; sect
++) {
146 sect_size
= flash_sector_size(fi
, sect
);
150 if (sect_size
!= flash_sector_size(fi
, sect
)) {
157 puts("cfi-mtd: devices with multiple sector sizes are"
162 mtd
->erasesize
= sect_size
;
167 int cfi_mtd_init(void)
169 struct mtd_info
*mtd
;
173 for (i
= 0; i
< CONFIG_SYS_MAX_FLASH_BANKS
; i
++) {
175 mtd
= &cfi_mtd_info
[i
];
177 memset(mtd
, 0, sizeof(struct mtd_info
));
179 error
= cfi_mtd_set_erasesize(mtd
, fi
);
183 mtd
->name
= CFI_MTD_DEV_NAME
;
184 mtd
->type
= MTD_NORFLASH
;
185 mtd
->flags
= MTD_CAP_NORFLASH
;
186 mtd
->size
= fi
->size
;
189 mtd
->erase
= cfi_mtd_erase
;
190 mtd
->read
= cfi_mtd_read
;
191 mtd
->write
= cfi_mtd_write
;
192 mtd
->sync
= cfi_mtd_sync
;
193 mtd
->lock
= cfi_mtd_lock
;
194 mtd
->unlock
= cfi_mtd_unlock
;
197 if (add_mtd_device(mtd
))