]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/mx1fs2/flash.c
2 * (C) 2000-2004 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
3 * (C) 2003 August Hoeraendl, Logotronic GmbH
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 #undef CONFIG_FLASH_16BIT
28 #define FLASH_BANK_SIZE MX1FS2_FLASH_BANK_SIZE
29 #define MAIN_SECT_SIZE MX1FS2_FLASH_SECT_SIZE
31 flash_info_t flash_info
[CFG_MAX_FLASH_BANKS
]; /* info for FLASH chips */
34 * NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
35 * has nothing to do with the flash chip being 8-bit or 16-bit.
37 #ifdef CONFIG_FLASH_16BIT
38 typedef unsigned short FLASH_PORT_WIDTH
;
39 typedef volatile unsigned short FLASH_PORT_WIDTHV
;
41 #define FLASH_ID_MASK 0xFFFF
43 typedef unsigned long FLASH_PORT_WIDTH
;
44 typedef volatile unsigned long FLASH_PORT_WIDTHV
;
46 #define FLASH_ID_MASK 0xFFFFFFFF
49 #define FPW FLASH_PORT_WIDTH
50 #define FPWV FLASH_PORT_WIDTHV
52 #define ORMASK(size) ((-size) & OR_AM_MSK)
54 /*-----------------------------------------------------------------------
58 static ulong
flash_get_size(FPWV
* addr
, flash_info_t
* info
);
59 static void flash_get_offsets(ulong base
, flash_info_t
* info
);
61 static void flash_reset(flash_info_t
* info
);
62 static int write_word_intel(flash_info_t
* info
, FPWV
* dest
, FPW data
);
63 static int write_word_amd(flash_info_t
* info
, FPWV
* dest
, FPW data
);
64 #define write_word(in, de, da) write_word_amd(in, de, da)
65 #ifdef CFG_FLASH_PROTECTION
66 static void flash_sync_real_protect(flash_info_t
* info
);
69 /*-----------------------------------------------------------------------
72 * sets up flash_info and returns size of FLASH (bytes)
80 for (i
= 0; i
< CFG_MAX_FLASH_BANKS
; i
++) {
82 flash_info
[i
].flash_id
=
83 (FLASH_MAN_AMD
& FLASH_VENDMASK
) |
84 (FLASH_AM640U
& FLASH_TYPEMASK
);
85 flash_info
[i
].size
= FLASH_BANK_SIZE
;
86 flash_info
[i
].sector_count
= CFG_MAX_FLASH_SECT
;
87 memset(flash_info
[i
].protect
, 0, CFG_MAX_FLASH_SECT
);
90 flashbase
= MX1FS2_FLASH_BASE
;
93 panic("configured too many flash banks!\n");
96 for (j
= 0; j
< flash_info
[i
].sector_count
; j
++) {
97 flash_info
[i
].start
[j
] = flashbase
+ j
* MAIN_SECT_SIZE
;
99 size
+= flash_info
[i
].size
;
102 /* Protect monitor and environment sectors */
103 flash_protect(FLAG_PROTECT_SET
,
105 CFG_FLASH_BASE
+ _bss_start
- _armboot_start
,
108 flash_protect(FLAG_PROTECT_SET
,
110 CONFIG_ENV_ADDR
+ CONFIG_ENV_SIZE
- 1, &flash_info
[0]);
115 /*-----------------------------------------------------------------------
118 flash_reset(flash_info_t
* info
)
120 FPWV
*base
= (FPWV
*) (info
->start
[0]);
122 /* Put FLASH back in read mode */
123 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
)
124 *base
= (FPW
) 0x00FF00FF; /* Intel Read Mode */
125 else if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_AMD
)
126 *base
= (FPW
) 0x00F000F0; /* AMD Read Mode */
129 /*-----------------------------------------------------------------------
133 flash_get_offsets(ulong base
, flash_info_t
* info
)
137 /* set up sector start address table */
138 if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
139 && (info
->flash_id
& FLASH_BTYPE
)) {
140 int bootsect_size
; /* number of bytes/boot sector */
141 int sect_size
; /* number of bytes/regular sector */
143 bootsect_size
= 0x00002000 * (sizeof (FPW
) / 2);
144 sect_size
= 0x00010000 * (sizeof (FPW
) / 2);
146 /* set sector offsets for bottom boot block type */
147 for (i
= 0; i
< 8; ++i
) {
148 info
->start
[i
] = base
+ (i
* bootsect_size
);
150 for (i
= 8; i
< info
->sector_count
; i
++) {
151 info
->start
[i
] = base
+ ((i
- 7) * sect_size
);
153 } else if ((info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_AMD
154 && (info
->flash_id
& FLASH_TYPEMASK
) == FLASH_AM640U
) {
156 int sect_size
; /* number of bytes/sector */
158 sect_size
= 0x00010000 * (sizeof (FPW
) / 2);
160 /* set up sector start address table (uniform sector type) */
161 for (i
= 0; i
< info
->sector_count
; i
++)
162 info
->start
[i
] = base
+ (i
* sect_size
);
167 /*-----------------------------------------------------------------------
171 flash_print_info(flash_info_t
* info
)
177 uchar botbootletter
[] = "B";
178 uchar topbootletter
[] = "T";
179 uchar botboottype
[] = "bottom boot sector";
180 uchar topboottype
[] = "top boot sector";
182 if (info
->flash_id
== FLASH_UNKNOWN
) {
183 printf("missing or unknown FLASH type\n");
187 switch (info
->flash_id
& FLASH_VENDMASK
) {
192 printf("BRIGHT MICRO ");
203 case FLASH_MAN_INTEL
:
207 printf("Unknown Vendor ");
211 /* check for top or bottom boot, if it applies */
212 if (info
->flash_id
& FLASH_BTYPE
) {
213 boottype
= botboottype
;
214 bootletter
= botbootletter
;
216 boottype
= topboottype
;
217 bootletter
= topbootletter
;
220 switch (info
->flash_id
& FLASH_TYPEMASK
) {
222 fmt
= "29LV641D (64 Mbit, uniform sectors)\n";
224 case FLASH_28F800C3B
:
225 case FLASH_28F800C3T
:
226 fmt
= "28F800C3%s (8 Mbit, %s)\n";
228 case FLASH_INTEL800B
:
229 case FLASH_INTEL800T
:
230 fmt
= "28F800B3%s (8 Mbit, %s)\n";
232 case FLASH_28F160C3B
:
233 case FLASH_28F160C3T
:
234 fmt
= "28F160C3%s (16 Mbit, %s)\n";
236 case FLASH_INTEL160B
:
237 case FLASH_INTEL160T
:
238 fmt
= "28F160B3%s (16 Mbit, %s)\n";
240 case FLASH_28F320C3B
:
241 case FLASH_28F320C3T
:
242 fmt
= "28F320C3%s (32 Mbit, %s)\n";
244 case FLASH_INTEL320B
:
245 case FLASH_INTEL320T
:
246 fmt
= "28F320B3%s (32 Mbit, %s)\n";
248 case FLASH_28F640C3B
:
249 case FLASH_28F640C3T
:
250 fmt
= "28F640C3%s (64 Mbit, %s)\n";
252 case FLASH_INTEL640B
:
253 case FLASH_INTEL640T
:
254 fmt
= "28F640B3%s (64 Mbit, %s)\n";
257 fmt
= "Unknown Chip Type\n";
261 printf(fmt
, bootletter
, boottype
);
263 printf(" Size: %ld MB in %d Sectors\n",
264 info
->size
>> 20, info
->sector_count
);
266 printf(" Sector Start Addresses:");
268 for (i
= 0; i
< info
->sector_count
; ++i
) {
273 printf(" %08lX%s", info
->start
[i
],
274 info
->protect
[i
] ? " (RO)" : " ");
280 /*-----------------------------------------------------------------------
284 * The following code cannot be run from FLASH!
289 flash_get_size(FPWV
* addr
, flash_info_t
* info
)
291 /* Write auto select command: read Manufacturer ID */
293 /* Write auto select command sequence and test FLASH answer */
294 addr
[0x0555] = (FPW
) 0x00AA00AA; /* for AMD, Intel ignores this */
295 addr
[0x02AA] = (FPW
) 0x00550055; /* for AMD, Intel ignores this */
296 addr
[0x0555] = (FPW
) 0x00900090; /* selects Intel or AMD */
298 /* The manufacturer codes are only 1 byte, so just use 1 byte.
299 * This works for any bus width and any FLASH device width.
301 switch (addr
[0] & 0xff) {
303 case (uchar
) AMD_MANUFACT
:
304 info
->flash_id
= FLASH_MAN_AMD
;
307 case (uchar
) INTEL_MANUFACT
:
308 info
->flash_id
= FLASH_MAN_INTEL
;
312 info
->flash_id
= FLASH_UNKNOWN
;
313 info
->sector_count
= 0;
318 /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
319 if (info
->flash_id
!= FLASH_UNKNOWN
)
322 case (FPW
) AMD_ID_LV640U
: /* 29LV640 and 29LV641 have same ID */
323 info
->flash_id
+= FLASH_AM640U
;
324 info
->sector_count
= 128;
325 info
->size
= 0x00800000 * (sizeof (FPW
) / 2);
326 break; /* => 8 or 16 MB */
328 case (FPW
) INTEL_ID_28F800C3B
:
329 info
->flash_id
+= FLASH_28F800C3B
;
330 info
->sector_count
= 23;
331 info
->size
= 0x00100000 * (sizeof (FPW
) / 2);
332 break; /* => 1 or 2 MB */
334 case (FPW
) INTEL_ID_28F800B3B
:
335 info
->flash_id
+= FLASH_INTEL800B
;
336 info
->sector_count
= 23;
337 info
->size
= 0x00100000 * (sizeof (FPW
) / 2);
338 break; /* => 1 or 2 MB */
340 case (FPW
) INTEL_ID_28F160C3B
:
341 info
->flash_id
+= FLASH_28F160C3B
;
342 info
->sector_count
= 39;
343 info
->size
= 0x00200000 * (sizeof (FPW
) / 2);
344 break; /* => 2 or 4 MB */
346 case (FPW
) INTEL_ID_28F160B3B
:
347 info
->flash_id
+= FLASH_INTEL160B
;
348 info
->sector_count
= 39;
349 info
->size
= 0x00200000 * (sizeof (FPW
) / 2);
350 break; /* => 2 or 4 MB */
352 case (FPW
) INTEL_ID_28F320C3B
:
353 info
->flash_id
+= FLASH_28F320C3B
;
354 info
->sector_count
= 71;
355 info
->size
= 0x00400000 * (sizeof (FPW
) / 2);
356 break; /* => 4 or 8 MB */
358 case (FPW
) INTEL_ID_28F320B3B
:
359 info
->flash_id
+= FLASH_INTEL320B
;
360 info
->sector_count
= 71;
361 info
->size
= 0x00400000 * (sizeof (FPW
) / 2);
362 break; /* => 4 or 8 MB */
364 case (FPW
) INTEL_ID_28F640C3B
:
365 info
->flash_id
+= FLASH_28F640C3B
;
366 info
->sector_count
= 135;
367 info
->size
= 0x00800000 * (sizeof (FPW
) / 2);
368 break; /* => 8 or 16 MB */
370 case (FPW
) INTEL_ID_28F640B3B
:
371 info
->flash_id
+= FLASH_INTEL640B
;
372 info
->sector_count
= 135;
373 info
->size
= 0x00800000 * (sizeof (FPW
) / 2);
374 break; /* => 8 or 16 MB */
377 info
->flash_id
= FLASH_UNKNOWN
;
378 info
->sector_count
= 0;
380 return (0); /* => no or unknown flash */
383 flash_get_offsets((ulong
) addr
, info
);
385 /* Put FLASH back in read mode */
392 #ifdef CFG_FLASH_PROTECTION
393 /*-----------------------------------------------------------------------
397 flash_sync_real_protect(flash_info_t
* info
)
399 FPWV
*addr
= (FPWV
*) (info
->start
[0]);
403 switch (info
->flash_id
& FLASH_TYPEMASK
) {
404 case FLASH_28F800C3B
:
405 case FLASH_28F800C3T
:
406 case FLASH_28F160C3B
:
407 case FLASH_28F160C3T
:
408 case FLASH_28F320C3B
:
409 case FLASH_28F320C3T
:
410 case FLASH_28F640C3B
:
411 case FLASH_28F640C3T
:
412 /* check for protected sectors */
413 *addr
= (FPW
) 0x00900090;
414 for (i
= 0; i
< info
->sector_count
; i
++) {
415 /* read sector protection at sector address, (A7 .. A0) = 0x02.
416 * D0 = 1 for each device if protected.
417 * If at least one device is protected the sector is marked
418 * protected, but mixed protected and unprotected devices
419 * within a sector should never happen.
421 sect
= (FPWV
*) (info
->start
[i
]);
423 (sect
[2] & (FPW
) (0x00010001)) ? 1 : 0;
426 /* Put FLASH back in read mode */
432 /* no hardware protect that we support */
438 /*-----------------------------------------------------------------------
442 flash_erase(flash_info_t
* info
, int s_first
, int s_last
)
445 int flag
, prot
, sect
;
446 int intel
= (info
->flash_id
& FLASH_VENDMASK
) == FLASH_MAN_INTEL
;
447 ulong start
, now
, last
;
450 if ((s_first
< 0) || (s_first
> s_last
)) {
451 if (info
->flash_id
== FLASH_UNKNOWN
) {
452 printf("- missing\n");
454 printf("- no sectors to erase\n");
459 switch (info
->flash_id
& FLASH_TYPEMASK
) {
460 case FLASH_INTEL800B
:
461 case FLASH_INTEL160B
:
462 case FLASH_INTEL320B
:
463 case FLASH_INTEL640B
:
464 case FLASH_28F800C3B
:
465 case FLASH_28F160C3B
:
466 case FLASH_28F320C3B
:
467 case FLASH_28F640C3B
:
472 printf("Can't erase unknown flash type %08lx - aborted\n",
478 for (sect
= s_first
; sect
<= s_last
; ++sect
) {
479 if (info
->protect
[sect
]) {
485 printf("- Warning: %d protected sectors will not be erased!\n",
491 start
= get_timer(0);
494 /* Start erase on unprotected sectors */
495 for (sect
= s_first
; sect
<= s_last
&& rcode
== 0; sect
++) {
497 if (info
->protect
[sect
] != 0) /* protected, skip it */
500 /* Disable interrupts which might cause a timeout here */
501 flag
= disable_interrupts();
503 addr
= (FPWV
*) (info
->start
[sect
]);
505 *addr
= (FPW
) 0x00500050; /* clear status register */
506 *addr
= (FPW
) 0x00200020; /* erase setup */
507 *addr
= (FPW
) 0x00D000D0; /* erase confirm */
509 /* must be AMD style if not Intel */
510 FPWV
*base
; /* first address in bank */
512 base
= (FPWV
*) (info
->start
[0]);
513 base
[0x0555] = (FPW
) 0x00AA00AA; /* unlock */
514 base
[0x02AA] = (FPW
) 0x00550055; /* unlock */
515 base
[0x0555] = (FPW
) 0x00800080; /* erase mode */
516 base
[0x0555] = (FPW
) 0x00AA00AA; /* unlock */
517 base
[0x02AA] = (FPW
) 0x00550055; /* unlock */
518 *addr
= (FPW
) 0x00300030; /* erase sector */
521 /* re-enable interrupts if necessary */
525 /* wait at least 50us for AMD, 80us for Intel.
530 while ((*addr
& (FPW
) 0x00800080) != (FPW
) 0x00800080) {
531 if ((now
= get_timer(0)) - start
> CFG_FLASH_ERASE_TOUT
) {
536 *addr
= (FPW
) 0x00B000B0;
539 flash_reset(info
); /* reset to read mode */
540 rcode
= 1; /* failed */
544 /* show that we're waiting */
545 if ((now
- last
) > 1000) { /* every second */
551 flash_reset(info
); /* reset to read mode */
558 /*-----------------------------------------------------------------------
559 * Copy memory to flash, returns:
562 * 2 - Flash not erased
565 bad_write_buff(flash_info_t
* info
, uchar
* src
, ulong addr
, ulong cnt
)
567 FPW data
= 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
568 int bytes
; /* number of bytes to program in current word */
569 int left
; /* number of bytes left to program */
572 for (left
= cnt
, res
= 0;
573 left
> 0 && res
== 0;
574 addr
+= sizeof (data
), left
-= sizeof (data
) - bytes
) {
576 bytes
= addr
& (sizeof (data
) - 1);
577 addr
&= ~(sizeof (data
) - 1);
579 /* combine source and destination data so can program
580 * an entire word of 16 or 32 bits
582 for (i
= 0; i
< sizeof (data
); i
++) {
584 if (i
< bytes
|| i
- bytes
>= left
)
585 data
+= *((uchar
*) addr
+ i
);
590 /* write one word to the flash */
591 switch (info
->flash_id
& FLASH_VENDMASK
) {
593 res
= write_word_amd(info
, (FPWV
*) addr
, data
);
595 case FLASH_MAN_INTEL
:
596 res
= write_word_intel(info
, (FPWV
*) addr
, data
);
599 /* unknown flash type, error! */
600 printf("missing or unknown FLASH type\n");
601 res
= 1; /* not really a timeout, but gives error */
610 * write_buf: - Copy memory to flash.
613 * @param src: source of copy transaction
614 * @param addr: where to copy to
615 * @param cnt: number of bytes to copy
621 write_buff(flash_info_t
* info
, uchar
* src
, ulong addr
, ulong cnt
)
628 wp
= (addr
& ~1); /* get lower word aligned address */
630 /* handle unaligned start bytes */
631 if ((l
= addr
- wp
) != 0) {
633 for (i
= 0, cp
= wp
; i
< l
; ++i
, ++cp
) {
634 data
= (data
>> 8) | (*(uchar
*) cp
<< 8);
636 for (; i
< 2 && cnt
> 0; ++i
) {
637 data
= (data
>> 8) | (*src
++ << 8);
641 for (; cnt
== 0 && i
< 2; ++i
, ++cp
) {
642 data
= (data
>> 8) | (*(uchar
*) cp
<< 8);
645 if ((rc
= write_word(info
, (FPWV
*)wp
, data
)) != 0) {
651 /* handle word aligned part */
653 /* data = *((vushort*)src); */
654 data
= *((FPW
*) src
);
655 if ((rc
= write_word(info
, (FPWV
*)wp
, data
)) != 0) {
667 * handle unaligned tail bytes
670 for (i
= 0, cp
= wp
; i
< 2 && cnt
> 0; ++i
, ++cp
) {
671 data
= (data
>> 8) | (*src
++ << 8);
674 for (; i
< 2; ++i
, ++cp
) {
675 data
= (data
>> 8) | (*(uchar
*) cp
<< 8);
678 return write_word(info
, (FPWV
*)wp
, data
);
681 /*-----------------------------------------------------------------------
682 * Write a word to Flash for AMD FLASH
683 * A word is 16 or 32 bits, whichever the bus width of the flash bank
684 * (not an individual chip) is.
689 * 2 - Flash not erased
692 write_word_amd(flash_info_t
* info
, FPWV
* dest
, FPW data
)
696 int res
= 0; /* result, assume success */
697 FPWV
*base
; /* first address in flash bank */
699 /* Check if Flash is (sufficiently) erased */
700 if ((*dest
& data
) != data
) {
704 base
= (FPWV
*) (info
->start
[0]);
705 /* Disable interrupts which might cause a timeout here */
706 flag
= disable_interrupts();
708 base
[0x0555] = (FPW
) 0x00AA00AA; /* unlock */
709 base
[0x02AA] = (FPW
) 0x00550055; /* unlock */
710 base
[0x0555] = (FPW
) 0x00A000A0; /* selects program mode */
712 *dest
= data
; /* start programming the data */
714 /* re-enable interrupts if necessary */
718 start
= get_timer(0);
720 /* data polling for D7 */
722 && (*dest
& (FPW
) 0x00800080) != (data
& (FPW
) 0x00800080)) {
723 if (get_timer(0) - start
> CFG_FLASH_WRITE_TOUT
) {
724 *dest
= (FPW
) 0x00F000F0; /* reset bank */
725 printf("SHA timeout\n");
733 /*-----------------------------------------------------------------------
734 * Write a word to Flash for Intel FLASH
735 * A word is 16 or 32 bits, whichever the bus width of the flash bank
736 * (not an individual chip) is.
741 * 2 - Flash not erased
744 write_word_intel(flash_info_t
* info
, FPWV
* dest
, FPW data
)
748 int res
= 0; /* result, assume success */
750 /* Check if Flash is (sufficiently) erased */
751 if ((*dest
& data
) != data
) {
755 /* Disable interrupts which might cause a timeout here */
756 flag
= disable_interrupts();
758 *dest
= (FPW
) 0x00500050; /* clear status register */
759 *dest
= (FPW
) 0x00FF00FF; /* make sure in read mode */
760 *dest
= (FPW
) 0x00400040; /* program setup */
762 *dest
= data
; /* start programming the data */
764 /* re-enable interrupts if necessary */
768 start
= get_timer(0);
770 while (res
== 0 && (*dest
& (FPW
) 0x00800080) != (FPW
) 0x00800080) {
771 if (get_timer(start
) > CFG_FLASH_WRITE_TOUT
) {
772 *dest
= (FPW
) 0x00B000B0; /* Suspend program */
777 if (res
== 0 && (*dest
& (FPW
) 0x00100010))
778 res
= 1; /* write failed, time out error is close enough */
780 *dest
= (FPW
) 0x00500050; /* clear status register */
781 *dest
= (FPW
) 0x00FF00FF; /* make sure in read mode */
786 #ifdef CFG_FLASH_PROTECTION
787 /*-----------------------------------------------------------------------
790 flash_real_protect(flash_info_t
* info
, long sector
, int prot
)
792 int rcode
= 0; /* assume success */
793 FPWV
*addr
; /* address of sector */
796 addr
= (FPWV
*) (info
->start
[sector
]);
798 switch (info
->flash_id
& FLASH_TYPEMASK
) {
799 case FLASH_28F800C3B
:
800 case FLASH_28F800C3T
:
801 case FLASH_28F160C3B
:
802 case FLASH_28F160C3T
:
803 case FLASH_28F320C3B
:
804 case FLASH_28F320C3T
:
805 case FLASH_28F640C3B
:
806 case FLASH_28F640C3T
:
807 flash_reset(info
); /* make sure in read mode */
808 *addr
= (FPW
) 0x00600060L
; /* lock command setup */
810 *addr
= (FPW
) 0x00010001L
; /* lock sector */
812 *addr
= (FPW
) 0x00D000D0L
; /* unlock sector */
813 flash_reset(info
); /* reset to read mode */
815 /* now see if it really is locked/unlocked as requested */
816 *addr
= (FPW
) 0x00900090;
817 /* read sector protection at sector address, (A7 .. A0) = 0x02.
818 * D0 = 1 for each device if protected.
819 * If at least one device is protected the sector is marked
820 * protected, but return failure. Mixed protected and
821 * unprotected devices within a sector should never happen.
823 value
= addr
[2] & (FPW
) 0x00010001;
825 info
->protect
[sector
] = 0;
826 else if (value
== (FPW
) 0x00010001)
827 info
->protect
[sector
] = 1;
829 /* error, mixed protected and unprotected */
831 info
->protect
[sector
] = 1;
833 if (info
->protect
[sector
] != prot
)
834 rcode
= 1; /* failed to protect/unprotect as requested */
836 /* reload all protection bits from hardware for now */
837 flash_sync_real_protect(info
);
842 /* no hardware protect that we support */
843 info
->protect
[sector
] = prot
;