]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cmd_eeprom.c
29e9faf2b23948953e8f5d56cbab251d7691be40
[karo-tx-uboot.git] / common / cmd_eeprom.c
1 /*
2  * (C) Copyright 2000, 2001
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
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.
12  *
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.
17  *
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,
21  * MA 02111-1307 USA
22  *
23  */
24
25 #include <common.h>
26 #include <config.h>
27 #include <command.h>
28 #include <i2c.h>
29
30 #if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
31
32 extern void eeprom_init  (void);
33 extern int  eeprom_read  (unsigned dev_addr, unsigned offset,
34                           uchar *buffer, unsigned cnt);
35 extern int  eeprom_write (unsigned dev_addr, unsigned offset,
36                           uchar *buffer, unsigned cnt);
37 #endif
38
39
40 #if defined(CFG_EEPROM_X40430)
41         /* Maximum number of times to poll for acknowledge after write */
42 #define MAX_ACKNOWLEDGE_POLLS   10
43 #endif
44
45 /* ------------------------------------------------------------------------- */
46
47 #if (CONFIG_COMMANDS & CFG_CMD_EEPROM)
48 int do_eeprom ( cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
49 {
50         const char *const fmt =
51                 "\nEEPROM @0x%lX %s: addr %08lx  off %04lx  count %ld ... ";
52
53 #if defined(CFG_I2C_MULTI_EEPROMS)
54         if (argc == 6) {
55                 ulong dev_addr = simple_strtoul (argv[2], NULL, 16);
56                 ulong addr = simple_strtoul (argv[3], NULL, 16);
57                 ulong off  = simple_strtoul (argv[4], NULL, 16);
58                 ulong cnt  = simple_strtoul (argv[5], NULL, 16);
59 #else
60         if (argc == 5) {
61                 ulong dev_addr = CFG_DEF_EEPROM_ADDR;
62                 ulong addr = simple_strtoul (argv[2], NULL, 16);
63                 ulong off  = simple_strtoul (argv[3], NULL, 16);
64                 ulong cnt  = simple_strtoul (argv[4], NULL, 16);
65 #endif /* CFG_I2C_MULTI_EEPROMS */
66
67 # ifndef CONFIG_SPI
68                 eeprom_init ();
69 # endif /* !CONFIG_SPI */
70
71                 if (strcmp (argv[1], "read") == 0) {
72                         int rcode;
73
74                         printf (fmt, dev_addr, argv[1], addr, off, cnt);
75
76                         rcode = eeprom_read (dev_addr, off, (uchar *) addr, cnt);
77
78                         printf ("done\n");
79                         return rcode;
80                 } else if (strcmp (argv[1], "write") == 0) {
81                         int rcode;
82
83                         printf (fmt, dev_addr, argv[1], addr, off, cnt);
84
85                         rcode = eeprom_write (dev_addr, off, (uchar *) addr, cnt);
86
87                         printf ("done\n");
88                         return rcode;
89                 }
90         }
91
92         printf ("Usage:\n%s\n", cmdtp->usage);
93         return 1;
94 }
95 #endif  /* CFG_CMD_EEPROM */
96
97 /*-----------------------------------------------------------------------
98  *
99  * for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
100  *   0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
101  *
102  * for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
103  *   0x00000nxx for EEPROM address selectors and page number at n.
104  */
105
106 #if (CONFIG_COMMANDS & CFG_CMD_EEPROM) || defined(CFG_ENV_IS_IN_EEPROM)
107
108 #ifndef CONFIG_SPI
109 #if !defined(CFG_I2C_EEPROM_ADDR_LEN) || CFG_I2C_EEPROM_ADDR_LEN < 1 || CFG_I2C_EEPROM_ADDR_LEN > 2
110 #error CFG_I2C_EEPROM_ADDR_LEN must be 1 or 2
111 #endif
112 #endif
113
114 int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
115 {
116         unsigned end = offset + cnt;
117         unsigned blk_off;
118         int rcode = 0;
119
120         /* Read data until done or would cross a page boundary.
121          * We must write the address again when changing pages
122          * because the next page may be in a different device.
123          */
124         while (offset < end) {
125                 unsigned alen, len, maxlen;
126 #if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
127                 uchar addr[2];
128
129                 blk_off = offset & 0xFF;        /* block offset */
130
131                 addr[0] = offset >> 8;          /* block number */
132                 addr[1] = blk_off;              /* block offset */
133                 alen    = 2;
134 #else
135                 uchar addr[3];
136
137                 blk_off = offset & 0xFF;        /* block offset */
138
139                 addr[0] = offset >> 16;         /* block number */
140                 addr[1] = offset >>  8;         /* upper address octet */
141                 addr[2] = blk_off;              /* lower address octet */
142                 alen    = 3;
143 #endif  /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
144
145                 addr[0] |= dev_addr;            /* insert device address */
146
147                 maxlen = 0x100 - blk_off;
148                 if (maxlen > I2C_RXTX_LEN)
149                         maxlen = I2C_RXTX_LEN;
150                 len    = end - offset;
151                 if (len > maxlen)
152                         len = maxlen;
153 #ifdef CONFIG_SPI
154                 spi_read (addr, alen, buffer, len);
155 #else
156                 if (i2c_read (addr[0], offset, alen-1, buffer, len) != 0)
157                         rcode = 1;
158 #endif
159                 buffer += len;
160                 offset += len;
161         }
162         return rcode;
163 }
164
165 /*-----------------------------------------------------------------------
166  *
167  * for CFG_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
168  *   0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
169  *
170  * for CFG_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
171  *   0x00000nxx for EEPROM address selectors and page number at n.
172  */
173
174 int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
175 {
176         unsigned end = offset + cnt;
177         unsigned blk_off;
178         int rcode = 0;
179
180 #if defined(CFG_EEPROM_X40430)
181         uchar   contr_r_addr[2];
182         uchar   addr_void[2];
183         uchar   contr_reg[2];
184         uchar   ctrl_reg_v;
185         int     i;
186 #endif
187
188         /* Write data until done or would cross a write page boundary.
189          * We must write the address again when changing pages
190          * because the address counter only increments within a page.
191          */
192
193         while (offset < end) {
194                 unsigned alen, len, maxlen;
195 #if CFG_I2C_EEPROM_ADDR_LEN == 1 && !defined(CONFIG_SPI_X)
196                 uchar addr[2];
197
198                 blk_off = offset & 0xFF;        /* block offset */
199
200                 addr[0] = offset >> 8;          /* block number */
201                 addr[1] = blk_off;              /* block offset */
202                 alen    = 2;
203 #else
204                 uchar addr[3];
205
206                 blk_off = offset & 0xFF;        /* block offset */
207
208                 addr[0] = offset >> 16;         /* block number */
209                 addr[1] = offset >>  8;         /* upper address octet */
210                 addr[2] = blk_off;              /* lower address octet */
211                 alen    = 3;
212 #endif  /* CFG_I2C_EEPROM_ADDR_LEN, CONFIG_SPI_X */
213
214                 addr[0] |= dev_addr;            /* insert device address */
215
216 #if defined(CFG_EEPROM_PAGE_WRITE_BITS)
217
218 #define EEPROM_PAGE_SIZE        (1 << CFG_EEPROM_PAGE_WRITE_BITS)
219 #define EEPROM_PAGE_OFFSET(x)   ((x) & (EEPROM_PAGE_SIZE - 1))
220
221                 maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off);
222 #else
223                 maxlen = 0x100 - blk_off;
224 #endif
225                 if (maxlen > I2C_RXTX_LEN)
226                         maxlen = I2C_RXTX_LEN;
227
228                 len = end - offset;
229                 if (len > maxlen)
230                         len = maxlen;
231 #ifdef CONFIG_SPI
232                 spi_write (addr, alen, buffer, len);
233 #else
234 #if defined(CFG_EEPROM_X40430)
235                 /* Get the value of the control register.
236                  * Set current address (internal pointer in the x40430)
237                  * to 0x1ff.
238                  */
239                 contr_r_addr[0] = 9;
240                 contr_r_addr[1] = 0xff;
241                 addr_void[0]    = 0;
242                 addr_void[1]    = addr[1];
243 #ifdef CFG_I2C_EEPROM_ADDR
244                 contr_r_addr[0] |= CFG_I2C_EEPROM_ADDR;
245                 addr_void[0]    |= CFG_I2C_EEPROM_ADDR;
246 #endif
247                 contr_reg[0] = 0xff;
248                 if (i2c_read (contr_r_addr[0], contr_r_addr[1], 1, contr_reg, 1) != 0) {
249                         rcode = 1;
250                 }
251                 ctrl_reg_v = contr_reg[0];
252
253                 /* Are any of the eeprom blocks write protected?
254                  */
255                 if (ctrl_reg_v & 0x18) {
256                         ctrl_reg_v &= ~0x18;   /* reset block protect bits  */
257                         ctrl_reg_v |=  0x02;   /* set write enable latch    */
258                         ctrl_reg_v &= ~0x04;   /* clear RWEL                */
259
260                         /* Set write enable latch.
261                          */
262                         contr_reg[0] = 0x02;
263                         if (i2c_write (contr_r_addr[0], 0xff, 1, contr_reg, 1) != 0) {
264                                 rcode = 1;
265                         }
266
267                         /* Set register write enable latch.
268                          */
269                         contr_reg[0] = 0x06;
270                         if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
271                                 rcode = 1;
272                         }
273
274                         /* Modify ctrl register.
275                          */
276                         contr_reg[0] = ctrl_reg_v;
277                         if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
278                                 rcode = 1;
279                         }
280
281                         /* The write (above) is an operation on NV memory.
282                          * These can take some time (~5ms), and the device
283                          * will not respond to further I2C messages till
284                          * it's completed the write.
285                          * So poll device for an I2C acknowledge.
286                          * When we get one we know we can continue with other
287                          * operations.
288                          */
289                         contr_reg[0] = 0;
290                         for (i = 0; i < MAX_ACKNOWLEDGE_POLLS; i++) {
291                                 if (i2c_read (addr_void[0], addr_void[1], 1, contr_reg, 1) == 1)
292                                         break;  /* got ack */
293 #if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
294                                 udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
295 #endif
296                         }
297                         if (i == MAX_ACKNOWLEDGE_POLLS) {
298                                 printf("EEPROM poll acknowledge failed\n");
299                                 rcode = 1;
300                         }
301                 }
302
303                 /* Is the write enable latch on?.
304                  */
305                 else if (!(ctrl_reg_v & 0x02)) {
306                         /* Set write enable latch.
307                          */
308                         contr_reg[0] = 0x02;
309                         if (i2c_write (contr_r_addr[0], 0xFF, 1, contr_reg, 1) != 0) {
310                                rcode = 1;
311                         }
312                 }
313                 /* Write is enabled ... now write eeprom value.
314                  */
315 #endif
316                 if (i2c_write (addr[0], offset, alen-1, buffer, len) != 0)
317                         rcode = 1;
318
319 #endif
320                 buffer += len;
321                 offset += len;
322
323 #if defined(CFG_EEPROM_PAGE_WRITE_DELAY_MS)
324                 udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
325 #endif
326         }
327         return rcode;
328 }
329
330 /*-----------------------------------------------------------------------
331  * Set default values
332  */
333 #ifndef CFG_I2C_SPEED
334 #define CFG_I2C_SPEED   50000
335 #endif
336
337 #ifndef CFG_I2C_SLAVE
338 #define CFG_I2C_SLAVE   0xFE
339 #endif
340
341 void eeprom_init  (void)
342 {
343 #if defined(CONFIG_SPI)
344         spi_init_f ();
345 #endif
346 #if defined(CONFIG_HARD_I2C) || \
347     defined(CONFIG_SOFT_I2C)
348         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
349 #endif
350 }
351 /*-----------------------------------------------------------------------
352  */
353 #endif  /* CFG_CMD_EEPROM */