blob: 3d23adfa298cf9387ff714712fde7a1aeeec39b2 [file] [log] [blame]
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +00001/*
2 * sst39sf020.c: driver for SST28SF040C flash 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 * 4 MEgabit (512K x 8) SuperFlash EEPROM, SST28SF040 data sheet
24 *
Ollie Lhocf29de82004-03-18 19:40:07 +000025 * ToDo: Consilidated to standard JEDEC code.
26 *
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000027 * $Id$
28 */
29
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000030#include <stdio.h>
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000031#include "flash.h"
32#include "jedec.h"
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000033#include "sst39sf020.h"
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000034
35#define AUTO_PG_ERASE1 0x20
36#define AUTO_PG_ERASE2 0xD0
Ollie Lhocbbf1252004-03-17 22:22:08 +000037#define AUTO_PGRM 0x10
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000038#define CHIP_ERASE 0x30
39#define RESET 0xFF
40#define READ_ID 0x90
41
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000042static __inline__ int erase_sector_39sf020 (volatile char * bios, unsigned long address)
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000043{
44 *bios = AUTO_PG_ERASE1;
45 *(bios + address) = AUTO_PG_ERASE2;
46
47 /* wait for Toggle bit ready */
48 toggle_ready_jedec(bios);
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000049
50 return(0);
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000051}
52
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000053static __inline__ int write_sector_39sf020(volatile char * bios,
Ollie Lhocf29de82004-03-18 19:40:07 +000054 unsigned char * src,
55 volatile unsigned char * dst,
56 unsigned int page_size)
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000057{
58 int i;
59 volatile char *Temp;
60
61 for (i = 0; i < page_size; i++) {
Ollie Lho6041bcd2002-07-18 03:32:00 +000062 if (*dst != 0xff) {
63 printf("FATAL: dst %p not erased (val 0x%x\n", dst, *dst);
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000064 return(-1);
Ollie Lho6041bcd2002-07-18 03:32:00 +000065 }
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000066 /* transfer data from source to destination */
67 if (*src == 0xFF) {
68 dst++, src++;
69 /* If the data is 0xFF, don't program it */
70 continue;
71 }
Ollie Lho6041bcd2002-07-18 03:32:00 +000072 Temp = (bios + 0x5555);
73 *Temp = 0xAA;
74 Temp = bios + 0x2AAA;
75 *Temp = 0x55;
76 Temp = bios + 0x5555;
77 *Temp = 0xA0;
Ronald G. Minnich213ee712002-04-10 16:01:38 +000078 *dst = *src;
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000079 toggle_ready_jedec(bios);
Ollie Lho6041bcd2002-07-18 03:32:00 +000080 if (*dst != *src)
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000081 printf("BAD! dst 0x%lx val 0x%x src 0x%x\n",
82 (unsigned long)dst, *dst, *src);
Ronald G. Minnich213ee712002-04-10 16:01:38 +000083 dst++, src++;
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000084 }
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000085
86 return(0);
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +000087}
88
89int probe_39sf020 (struct flashchip * flash)
90{
91 volatile char * bios = flash->virt_addr;
92 unsigned char id1, id2;
93
94 *(volatile char *) (bios + 0x5555) = 0xAA;
95 myusec_delay(10);
96 *(volatile char *) (bios + 0x2AAA) = 0x55;
97 myusec_delay(10);
98 *(volatile char *) (bios + 0x5555) = 0x90;
99
100 myusec_delay(10);
101
102 id1 = *(volatile unsigned char *) bios;
103 id2 = *(volatile unsigned char *) (bios + 0x01);
104
105 *(volatile char *) (bios + 0x5555) = 0xAA;
106 *(volatile char *) (bios + 0x2AAA) = 0x55;
107 *(volatile char *) (bios + 0x5555) = 0xF0;
108
109 myusec_delay(10);
110
Ronald G. Minnichd4228fd2003-02-28 17:21:38 +0000111 printf("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
112
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +0000113 if (id1 == flash->manufacture_id && id2 == flash->model_id)
114 return 1;
115
116 return 0;
117}
118
119int erase_39sf020 (struct flashchip * flash)
120{
Ronald G. Minnich213ee712002-04-10 16:01:38 +0000121 volatile unsigned char * bios = flash->virt_addr;
Ollie Lho6041bcd2002-07-18 03:32:00 +0000122 volatile unsigned char *Temp;
123
Ronald G. Minnich213ee712002-04-10 16:01:38 +0000124 /* Issue the Sector Erase command to 39SF020 */
Ronald G. Minnich213ee712002-04-10 16:01:38 +0000125 Temp = bios + 0x5555; /* set up address to be C000:5555h */
126 *Temp = 0xAA; /* write data 0xAA to the address */
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +0000127 myusec_delay(10);
Ronald G. Minnich213ee712002-04-10 16:01:38 +0000128 Temp = bios + 0x2AAA; /* set up address to be C000:2AAAh */
129 *Temp = 0x55; /* write data 0x55 to the address */
130 myusec_delay(10);
131 Temp = bios + 0x5555; /* set up address to be C000:5555h */
132 *Temp = 0x80; /* write data 0x80 to the address */
133 myusec_delay(10);
134 Temp = bios + 0x5555; /* set up address to be C000:5555h */
135 *Temp = 0xAA; /* write data 0xAA to the address */
136 myusec_delay(10);
137 Temp = bios + 0x2AAA; /* set up address to be C000:2AAAh */
138 *Temp = 0x55; /* write data 0x55 to the address */
139 myusec_delay(10);
140 Temp = bios + 0x5555; /* set up address to be C000:5555h */
141 *Temp = 0x10; /* write data 0x55 to the address */
142
Ronald G. Minniche5559572003-03-28 03:29:43 +0000143 myusec_delay(50000);
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +0000144
145 return(0);
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +0000146}
147
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +0000148int write_39sf020 (struct flashchip * flash, unsigned char * buf)
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +0000149{
150 int i;
151 int total_size = flash->total_size * 1024, page_size = flash->page_size;
152 volatile char * bios = flash->virt_addr;
153
Ronald G. Minnich213ee712002-04-10 16:01:38 +0000154 erase_39sf020(flash);
Ollie Lhocf29de82004-03-18 19:40:07 +0000155
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +0000156 printf ("Programming Page: ");
157 for (i = 0; i < total_size/page_size; i++) {
158 /* erase the page before programming */
159 //erase_sector_39sf020(bios, i * page_size);
160
161 /* write to the sector */
162 printf ("%04d at address: 0x%08x", i, i * page_size);
163 write_sector_39sf020(bios, buf + i * page_size, bios + i * page_size,
164 page_size);
165 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");
Ronald G. Minniche5559572003-03-28 03:29:43 +0000166 fflush(stdout);
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +0000167 }
168 printf("\n");
169
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +0000170 return(0);
Ronald G. Minnich5e8dfff2002-03-21 22:41:11 +0000171}