blob: 89cdff98063b59302f738dfa897ea1f5b4a7fa5a [file] [log] [blame]
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +00001/*
2 * am29f040.c: driver for programming AMD am29f040b models
3 *
4 *
5 * Copyright 2000 Silicon Integrated System Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 *
22 * Reference:
23 * AMD Am29F040B data sheet
24 * $Id$
25 */
26
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000027#include <stdio.h>
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000028#include "flash.h"
29#include "jedec.h"
30
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000031static __inline__ int erase_sector_29f040b (volatile char * bios, unsigned long address)
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000032{
33 *(bios + 0x555) = 0xAA;
34 *(bios + 0x2AA) = 0x55;
35 *(bios + 0x555) = 0x80;
36 *(bios + 0x555) = 0xAA;
37 *(bios + 0x2AA) = 0x55;
38 *(bios + address) = 0x30;
39
40 sleep(2);
41
42 /* wait for Toggle bit ready */
43 toggle_ready_jedec(bios + address);
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000044
45 return(0);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000046}
47
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000048static __inline__ int write_sector_29f040b(volatile char * bios, unsigned char * src,
Ronald G. Minnichef5779d2002-01-29 20:18:02 +000049 volatile unsigned char * dst, unsigned int page_size)
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000050{
51 int i;
52
53 for (i = 0; i < page_size; i++) {
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000054 printf("0x%08lx", (unsigned long) dst - (unsigned long) bios);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000055
56 *(bios + 0x555) = 0xAA;
57 *(bios + 0x2AA) = 0x55;
58 *(bios + 0x555) = 0xA0;
59 *dst++ = *src++;
60
61 /* wait for Toggle bit ready */
62 toggle_ready_jedec(bios);
63
64 printf("\b\b\b\b\b\b\b\b\b\b");
65 }
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000066
67 return(0);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000068}
69
70int probe_29f040b (struct flashchip * flash)
71{
Ronald G. Minnichef5779d2002-01-29 20:18:02 +000072 volatile char * bios = flash->virt_addr;
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000073 unsigned char id1, id2;
74
75 *(bios + 0x555) = 0xAA;
76 *(bios + 0x2AA) = 0x55;
77 *(bios + 0x555) = 0x90;
78
79 id1 = *(unsigned char *) bios;
80 id2 = *(unsigned char *) (bios + 0x01);
81
82 *bios = 0xF0;
83
Ronald G. Minnichef5779d2002-01-29 20:18:02 +000084 myusec_delay(10);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000085
Ronald G. Minnichd4228fd2003-02-28 17:21:38 +000086 printf("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000087 if (id1 == flash->manufacture_id && id2 == flash->model_id)
88 return 1;
89
90 return 0;
91}
92
93int erase_29f040b (struct flashchip * flash)
94{
Ronald G. Minnichef5779d2002-01-29 20:18:02 +000095 volatile char * bios = flash->virt_addr;
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +000096
97 *(bios + 0x555) = 0xAA;
98 *(bios + 0x2AA) = 0x55;
99 *(bios + 0x555) = 0x80;
100 *(bios + 0x555) = 0xAA;
101 *(bios + 0x2AA) = 0x55;
102 *(bios + 0x555) = 0x10;
103
Ronald G. Minnichef5779d2002-01-29 20:18:02 +0000104 myusec_delay(10);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +0000105 toggle_ready_jedec(bios);
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +0000106
107 return(0);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +0000108}
109
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +0000110int write_29f040b (struct flashchip * flash, unsigned char * buf)
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +0000111{
112 int i;
113 int total_size = flash->total_size * 1024, page_size = flash->page_size;
Ronald G. Minnichef5779d2002-01-29 20:18:02 +0000114 volatile char * bios = flash->virt_addr;
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +0000115
116 printf ("Programming Page: ");
117 for (i = 0; i < total_size/page_size; i++) {
118 /* erase the page before programming */
119 erase_sector_29f040b(bios, i * page_size);
120
121 /* write to the sector */
122 printf ("%04d at address: ", i);
123 write_sector_29f040b(bios, buf + i * page_size, bios + i * page_size,
124 page_size);
125 printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
126 }
127 printf("\n");
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +0000128
129 return(0);
Ronald G. Minnich5e5f75e2002-01-29 18:21:41 +0000130}