blob: 7fcb3ee72c0d87c4c469cee475700e9fadc55e59 [file] [log] [blame]
Ronald G. Minniche3dad012004-02-10 21:34:18 +00001/*
2 * pm49fl004.c: driver for Pm49FL004 flash models.
3 *
4 *
5 * Copyright 2004 Tyan 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 */
23
24#include <stdio.h>
25#include "flash.h"
26#include "jedec.h"
27#include "pm49fl004.h"
28
29#define AUTO_PGRM 0x10
30#define CHIP_ERASE 0x30
31#define RESET 0xFF
32#define READ_ID 0x90
33
34static __inline__ void protect_49fl004 (volatile char * bios)
35{
36 /* ask compiler not to optimize this */
37 volatile unsigned char tmp;
38
39 tmp = *(volatile unsigned char *) (bios + 0x1823);
40 tmp = *(volatile unsigned char *) (bios + 0x1820);
41 tmp = *(volatile unsigned char *) (bios + 0x1822);
42 tmp = *(volatile unsigned char *) (bios + 0x0418);
43 tmp = *(volatile unsigned char *) (bios + 0x041B);
44 tmp = *(volatile unsigned char *) (bios + 0x0419);
45 tmp = *(volatile unsigned char *) (bios + 0x040A);
46}
47
48static __inline__ void unprotect_49fl004 (volatile char * bios)
49{
50 /* ask compiler not to optimize this */
51 volatile unsigned char tmp;
52
53 tmp = *(volatile unsigned char *) (bios + 0x1823);
54 tmp = *(volatile unsigned char *) (bios + 0x1820);
55 tmp = *(volatile unsigned char *) (bios + 0x1822);
56 tmp = *(volatile unsigned char *) (bios + 0x0418);
57 tmp = *(volatile unsigned char *) (bios + 0x041B);
58 tmp = *(volatile unsigned char *) (bios + 0x0419);
59 tmp = *(volatile unsigned char *) (bios + 0x041A);
60}
61
62static __inline__ int erase_block_49fl004 ( volatile unsigned char * bios ,unsigned long address)
63{
64 volatile unsigned char *Temp;
65
66 Temp = bios + 0x5555; /* set up address to be C000:5555h */
67 *Temp = 0xAA; /* write data 0xAA to the address */
68 myusec_delay(10);
69 Temp = bios + 0x2AAA; /* set up address to be C000:2AAAh */
70 *Temp = 0x55; /* write data 0x55 to the address */
71 myusec_delay(10);
72 Temp = bios + 0x5555; /* set up address to be C000:5555h */
73 *Temp = 0x80; /* write data 0x80 to the address */
74 myusec_delay(10);
75 Temp = bios + 0x5555; /* set up address to be C000:5555h */
76 *Temp = 0xAA; /* write data 0xAA to the address */
77 myusec_delay(10);
78 Temp = bios + 0x2AAA; /* set up address to be C000:2AAAh */
79 *Temp = 0x55; /* write data 0x55 to the address */
80 myusec_delay(10);
81 Temp = bios + address; /* set up address to be C000:5555h */
82 *Temp = 0x50; /* write data 0x55 to the address */
83
84 /* wait for Toggle bit ready */
85 toggle_ready_jedec(bios);
86
87 return(0);
88}
89static __inline__ int write_block_49fl004(volatile char * bios,
90 unsigned char * src,
91 volatile unsigned char * dst,
92 unsigned int page_size)
93{
94 int i;
95 volatile char *Temp;
96
97 for (i = 0; i < page_size; i++) {
98 if (*dst != 0xff) {
99 printf("FATAL: dst %p not erased (val 0x%x\n", dst, *dst);
100 return(-1);
101 }
102 /* transfer data from source to destination */
103 if (*src == 0xFF) {
104 dst++, src++;
105 /* If the data is 0xFF, don't program it */
106 continue;
107 }
108 Temp = (bios + 0x5555);
109 *Temp = 0xAA;
110 Temp = bios + 0x2AAA;
111 *Temp = 0x55;
112 Temp = bios + 0x5555;
113 *Temp = 0xA0;
114 *dst = *src;
115 toggle_ready_jedec(bios);
116 if (*dst != *src)
117 printf("BAD! dst 0x%lx val 0x%x src 0x%x\n",
118 (unsigned long)dst, *dst, *src);
119 dst++, src++;
120 }
121
122 return(0);
123}
124
125int probe_49fl004 (struct flashchip * flash)
126{
127 volatile char * bios = flash->virt_addr;
128 unsigned char id1, id2;
129
130 *(volatile char *) (bios + 0x5555) = 0xAA;
131 myusec_delay(10);
132 *(volatile char *) (bios + 0x2AAA) = 0x55;
133 myusec_delay(10);
134 *(volatile char *) (bios + 0x5555) = 0x90;
135
136 myusec_delay(10);
137
138 id1 = *(volatile unsigned char *) bios;
139 id2 = *(volatile unsigned char *) (bios + 0x01);
140
141 *(volatile char *) (bios + 0x5555) = 0xAA;
142 *(volatile char *) (bios + 0x2AAA) = 0x55;
143 *(volatile char *) (bios + 0x5555) = 0xF0;
144
145 myusec_delay(10);
146
147 printf("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
148
149 if (id1 == flash->manufacture_id && id2 == flash->model_id)
150 return 1;
151
152 return 0;
153}
154
155int erase_49fl004 (struct flashchip * flash)
156{
157 volatile unsigned char * bios = flash->virt_addr;
158 volatile unsigned char *Temp;
159
160 Temp = bios + 0x5555; /* set up address to be C000:5555h */
161 *Temp = 0xAA; /* write data 0xAA to the address */
162 myusec_delay(10);
163 Temp = bios + 0x2AAA; /* set up address to be C000:2AAAh */
164 *Temp = 0x55; /* write data 0x55 to the address */
165 myusec_delay(10);
166 Temp = bios + 0x5555; /* set up address to be C000:5555h */
167 *Temp = 0x80; /* write data 0x80 to the address */
168 myusec_delay(10);
169 Temp = bios + 0x5555; /* set up address to be C000:5555h */
170 *Temp = 0xAA; /* write data 0xAA to the address */
171 myusec_delay(10);
172 Temp = bios + 0x2AAA; /* set up address to be C000:2AAAh */
173 *Temp = 0x55; /* write data 0x55 to the address */
174 myusec_delay(10);
175 Temp = bios + 0x5555; /* set up address to be C000:5555h */
176 *Temp = 0x10; /* write data 0x10 to the address */
177
178
179 /* wait for Toggle bit ready */
180 toggle_ready_jedec(bios);
181
182 return(0);
183}
184
185int write_49fl004 (struct flashchip * flash, unsigned char * buf)
186{
187 int i;
188 int total_size = flash->total_size * 1024, page_size = flash->page_size;
189 volatile char * bios = flash->virt_addr;
190
191// unprotect_49fl004 (bios);
192// erase_49fl004(flash);
193 printf ("Programming Page: ");
194 for (i = 0; i < total_size/page_size; i++) {
195 /* erase the page before programming */
196 erase_block_49fl004(bios, i * page_size);
197
198 /* write to the sector */
199 printf ("%04d at address: 0x%08x", i, i * page_size);
200 write_block_49fl004(bios, buf + i * page_size, bios + i * page_size,
201 page_size);
202 printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
203 fflush(stdout);
204 }
205 printf("\n");
206
207// protect_49fl004 (bios);
208
209 return(0);
210}