7797d0ec9c9c6446f961614f7baac53f64259378
[oweals/u-boot.git] / common / cmd_eeprom.c
1 /*
2  * (C) Copyright 2000, 2001
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * Support for read and write access to EEPROM like memory devices. This
10  * includes regular EEPROM as well as  FRAM (ferroelectic nonvolaile RAM).
11  * FRAM devices read and write data at bus speed. In particular, there is no
12  * write delay. Also, there is no limit imposed on the number of bytes that can
13  * be transferred with a single read or write.
14  *
15  * Use the following configuration options to ensure no unneeded performance
16  * degradation (typical for EEPROM) is incured for FRAM memory:
17  *
18  * #define CONFIG_SYS_I2C_FRAM
19  * #undef CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS
20  *
21  */
22
23 #include <common.h>
24 #include <config.h>
25 #include <command.h>
26 #include <i2c.h>
27
28 #ifndef CONFIG_SYS_I2C_SPEED
29 #define CONFIG_SYS_I2C_SPEED    50000
30 #endif
31
32 /*
33  * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 2 (16-bit EEPROM address) offset is
34  *   0x000nxxxx for EEPROM address selectors at n, offset xxxx in EEPROM.
35  *
36  * for CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1 (8-bit EEPROM page address) offset is
37  *   0x00000nxx for EEPROM address selectors and page number at n.
38  */
39 #if !defined(CONFIG_SPI) || defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
40 #if !defined(CONFIG_SYS_I2C_EEPROM_ADDR_LEN) || \
41     (CONFIG_SYS_I2C_EEPROM_ADDR_LEN < 1) || \
42     (CONFIG_SYS_I2C_EEPROM_ADDR_LEN > 2)
43 #error CONFIG_SYS_I2C_EEPROM_ADDR_LEN must be 1 or 2
44 #endif
45 #endif
46
47 #if defined(CONFIG_SYS_EEPROM_WREN)
48 extern int eeprom_write_enable (unsigned dev_addr, int state);
49 #endif
50
51 void eeprom_init(void)
52 {
53         /* SPI EEPROM */
54 #if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
55         spi_init_f ();
56 #endif
57
58         /* I2C EEPROM */
59 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C_SOFT)
60         i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
61 #endif
62 }
63
64 static int eeprom_rw_block(unsigned offset, uchar *addr, unsigned alen,
65                            uchar *buffer, unsigned len, bool read)
66 {
67         int ret = 0;
68
69         /* SPI */
70 #if defined(CONFIG_SPI) && !defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
71         if (read)
72                 spi_read(addr, alen, buffer, len);
73         else
74                 spi_write(addr, alen, buffer, len);
75 #else   /* I2C */
76
77 #if defined(CONFIG_SYS_I2C_EEPROM_BUS)
78         i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS);
79 #endif
80
81         if (read)
82                 ret = i2c_read(addr[0], offset, alen - 1, buffer, len);
83         else
84                 ret = i2c_write(addr[0], offset, alen - 1, buffer, len);
85
86         if (ret)
87                 ret = 1;
88 #endif
89         return ret;
90 }
91
92 int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
93 {
94         unsigned end = offset + cnt;
95         unsigned blk_off;
96         int rcode = 0;
97
98         /*
99          * Read data until done or would cross a page boundary.
100          * We must write the address again when changing pages
101          * because the next page may be in a different device.
102          */
103         while (offset < end) {
104                 unsigned alen, len;
105 #if !defined(CONFIG_SYS_I2C_FRAM)
106                 unsigned maxlen;
107 #endif
108
109 #if CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1
110                 uchar addr[2];
111
112                 blk_off = offset & 0xFF;        /* block offset */
113
114                 addr[0] = offset >> 8;          /* block number */
115                 addr[1] = blk_off;              /* block offset */
116                 alen    = 2;
117 #else
118                 uchar addr[3];
119
120                 blk_off = offset & 0xFF;        /* block offset */
121
122                 addr[0] = offset >> 16;         /* block number */
123                 addr[1] = offset >>  8;         /* upper address octet */
124                 addr[2] = blk_off;              /* lower address octet */
125                 alen    = 3;
126 #endif  /* CONFIG_SYS_I2C_EEPROM_ADDR_LEN */
127
128                 addr[0] |= dev_addr;            /* insert device address */
129
130                 len = end - offset;
131
132                 /*
133                  * For a FRAM device there is no limit on the number of the
134                  * bytes that can be ccessed with the single read or write
135                  * operation.
136                  */
137 #if !defined(CONFIG_SYS_I2C_FRAM)
138                 maxlen = 0x100 - blk_off;
139                 if (maxlen > I2C_RXTX_LEN)
140                         maxlen = I2C_RXTX_LEN;
141                 if (len > maxlen)
142                         len = maxlen;
143 #endif
144
145                 rcode = eeprom_rw_block(offset, addr, alen, buffer, len, 1);
146
147                 buffer += len;
148                 offset += len;
149         }
150
151         return rcode;
152 }
153
154 int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt)
155 {
156         unsigned end = offset + cnt;
157         unsigned blk_off;
158         int rcode = 0;
159
160 #if defined(CONFIG_SYS_EEPROM_WREN)
161         eeprom_write_enable (dev_addr,1);
162 #endif
163         /*
164          * Write data until done or would cross a write page boundary.
165          * We must write the address again when changing pages
166          * because the address counter only increments within a page.
167          */
168
169         while (offset < end) {
170                 unsigned alen, len;
171 #if !defined(CONFIG_SYS_I2C_FRAM)
172                 unsigned maxlen;
173 #endif
174
175 #if CONFIG_SYS_I2C_EEPROM_ADDR_LEN == 1
176                 uchar addr[2];
177
178                 blk_off = offset & 0xFF;        /* block offset */
179
180                 addr[0] = offset >> 8;          /* block number */
181                 addr[1] = blk_off;              /* block offset */
182                 alen    = 2;
183 #else
184                 uchar addr[3];
185
186                 blk_off = offset & 0xFF;        /* block offset */
187
188                 addr[0] = offset >> 16;         /* block number */
189                 addr[1] = offset >>  8;         /* upper address octet */
190                 addr[2] = blk_off;              /* lower address octet */
191                 alen    = 3;
192 #endif  /* CONFIG_SYS_I2C_EEPROM_ADDR_LEN */
193
194                 addr[0] |= dev_addr;            /* insert device address */
195
196                 len = end - offset;
197
198                 /*
199                  * For a FRAM device there is no limit on the number of the
200                  * bytes that can be accessed with the single read or write
201                  * operation.
202                  */
203 #if !defined(CONFIG_SYS_I2C_FRAM)
204
205 #if defined(CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)
206
207 #define EEPROM_PAGE_SIZE        (1 << CONFIG_SYS_EEPROM_PAGE_WRITE_BITS)
208 #define EEPROM_PAGE_OFFSET(x)   ((x) & (EEPROM_PAGE_SIZE - 1))
209
210                 maxlen = EEPROM_PAGE_SIZE - EEPROM_PAGE_OFFSET(blk_off);
211 #else
212                 maxlen = 0x100 - blk_off;
213 #endif
214                 if (maxlen > I2C_RXTX_LEN)
215                         maxlen = I2C_RXTX_LEN;
216
217                 if (len > maxlen)
218                         len = maxlen;
219 #endif
220
221                 rcode = eeprom_rw_block(offset, addr, alen, buffer, len, 0);
222
223                 buffer += len;
224                 offset += len;
225
226 #if defined(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS)
227                 udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
228 #endif
229         }
230 #if defined(CONFIG_SYS_EEPROM_WREN)
231         eeprom_write_enable (dev_addr,0);
232 #endif
233         return rcode;
234 }
235
236 static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
237 {
238         const char *const fmt =
239                 "\nEEPROM @0x%lX %s: addr %08lx  off %04lx  count %ld ... ";
240         char * const *args = &argv[2];
241         int rcode;
242         ulong dev_addr, addr, off, cnt;
243
244         switch (argc) {
245 #ifdef CONFIG_SYS_DEF_EEPROM_ADDR
246         case 5:
247                 dev_addr = CONFIG_SYS_DEF_EEPROM_ADDR;
248                 break;
249 #endif
250         case 6:
251                 dev_addr = simple_strtoul(*args++, NULL, 16);
252                 break;
253         default:
254                 return CMD_RET_USAGE;
255         }
256
257         addr = simple_strtoul(*args++, NULL, 16);
258         off = simple_strtoul(*args++, NULL, 16);
259         cnt = simple_strtoul(*args++, NULL, 16);
260
261 # if !defined(CONFIG_SPI) || defined(CONFIG_ENV_EEPROM_IS_ON_I2C)
262         eeprom_init ();
263 # endif /* !CONFIG_SPI */
264
265         if (strcmp (argv[1], "read") == 0) {
266                 printf(fmt, dev_addr, argv[1], addr, off, cnt);
267
268                 rcode = eeprom_read(dev_addr, off, (uchar *) addr, cnt);
269
270                 puts ("done\n");
271                 return rcode;
272         } else if (strcmp (argv[1], "write") == 0) {
273                 printf(fmt, dev_addr, argv[1], addr, off, cnt);
274
275                 rcode = eeprom_write(dev_addr, off, (uchar *) addr, cnt);
276
277                 puts ("done\n");
278                 return rcode;
279         }
280
281         return CMD_RET_USAGE;
282 }
283
284 U_BOOT_CMD(
285         eeprom, 6,      1,      do_eeprom,
286         "EEPROM sub-system",
287         "read  devaddr addr off cnt\n"
288         "eeprom write devaddr addr off cnt\n"
289         "       - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'"
290 )