GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / arch / mips / cpu / sb1250 / src / dev_sb1250_at24c02eeprom.c
blob68ede5dfc2db0d7a64048f9f4b95181798dae284
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * ATMEL AT24C02 EEPROM driver File: dev_sb1250_at24c02eeprom.c
5 *
6 * This module contains a CFE driver for a ATMEL AT24C02 EEPROM
7 *
8 * Author: Binh Vo (binh@broadcom.com)
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
48 #include "sbmips.h"
49 #include "lib_types.h"
50 #include "lib_malloc.h"
51 #include "lib_printf.h"
53 #include "cfe_iocb.h"
54 #include "cfe_device.h"
55 #include "cfe_ioctl.h"
56 #include "cfe_timer.h"
58 #include "sb1250_defs.h"
59 #include "sb1250_regs.h"
60 #include "sb1250_smbus.h"
63 /* *********************************************************************
64 * Forward Declarations
65 ********************************************************************* */
67 static void sb1250_at24c02eeprom_probe(cfe_driver_t *drv,
68 unsigned long probe_a, unsigned long probe_b,
69 void *probe_ptr);
72 static int sb1250_at24c02eeprom_open(cfe_devctx_t *ctx);
73 static int sb1250_at24c02eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
74 static int sb1250_at24c02eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
75 static int sb1250_at24c02eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
76 static int sb1250_at24c02eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
77 static int sb1250_at24c02eeprom_close(cfe_devctx_t *ctx);
79 /* *********************************************************************
80 * Dispatch tables
81 ********************************************************************* */
83 #define AT24C02_EEPROM_SIZE 256
85 const static cfe_devdisp_t sb1250_at24c02eeprom_dispatch = {
86 sb1250_at24c02eeprom_open,
87 sb1250_at24c02eeprom_read,
88 sb1250_at24c02eeprom_inpstat,
89 sb1250_at24c02eeprom_write,
90 sb1250_at24c02eeprom_ioctl,
91 sb1250_at24c02eeprom_close,
92 NULL,
93 NULL
96 const cfe_driver_t sb1250_at24c02eeprom = {
97 "ATMEL AT24C02 SPD EEPROM",
98 "eeprom",
99 CFE_DEV_NVRAM,
100 &sb1250_at24c02eeprom_dispatch,
101 sb1250_at24c02eeprom_probe
104 typedef struct sb1250_at24c02eeprom_s {
105 int smbus_channel;
106 int smbus_address;
107 int env_offset;
108 int env_size;
109 unsigned char data[AT24C02_EEPROM_SIZE];
110 } sb1250_at24c02eeprom_t;
113 /* *********************************************************************
114 * smbus_init(chan)
116 * Initialize the specified SMBus channel
118 * Input parameters:
119 * chan - channel # (0 or 1)
121 * Return value:
122 * nothing
123 ********************************************************************* */
125 static void smbus_init(int chan)
127 uintptr_t reg;
129 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_FREQ));
131 SBWRITECSR(reg,K_SMB_FREQ_100KHZ);
133 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CONTROL));
135 SBWRITECSR(reg,0); /* not in direct mode, no interrupts, will poll */
139 /* *********************************************************************
140 * smbus_waitready(chan)
142 * Wait until the SMBus channel is ready. We simply poll
143 * the busy bit until it clears.
145 * Input parameters:
146 * chan - channel (0 or 1)
148 * Return value:
149 * nothing
150 ********************************************************************* */
151 static int smbus_waitready(int chan)
153 uintptr_t reg;
154 uint64_t status;
156 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_STATUS));
158 for (;;) {
159 status = SBREADCSR(reg);
160 if (status & M_SMB_BUSY) continue;
161 break;
164 if (status & M_SMB_ERROR) {
166 SBWRITECSR(reg,(status & M_SMB_ERROR));
167 return -1;
169 return 0;
172 /* *********************************************************************
173 * smbus_readbyte(chan,slaveaddr,devaddr)
175 * Read a byte from the chip.
177 * Input parameters:
178 * chan - SMBus channel
179 * slaveaddr - SMBus slave address
180 * devaddr - byte within the at24c02 device to read
182 * Return value:
183 * 0 if ok
184 * else -1
185 ********************************************************************* */
187 static int smbus_readbyte(int chan,int slaveaddr,int devaddr)
189 uintptr_t reg;
190 int err;
193 * Make sure the bus is idle (probably should
194 * ignore error here)
197 if (smbus_waitready(chan) < 0) return -1;
200 * Write the device address to smb_cmd field of command register
203 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD));
204 SBWRITECSR(reg,devaddr);
207 * Start the command
210 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START));
211 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR1BYTE) | slaveaddr);
214 * Wait till done
217 err = smbus_waitready(chan);
218 if (err < 0) return err;
221 * Read the data byte
224 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_RD1BYTE) | slaveaddr);
226 err = smbus_waitready(chan);
227 if (err < 0) return err;
229 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
230 err = SBREADCSR(reg);
232 return (err & 0xFF);
235 /* *********************************************************************
236 * smbus_writebyte(chan,slaveaddr,devaddr,b)
238 * write a byte from the chip.
240 * Input parameters:
241 * chan - SMBus channel
242 * slaveaddr - SMBus slave address
243 * devaddr - byte within the at24c02 device to read
244 * b - byte to write
246 * Return value:
247 * 0 if ok
248 * else -1
249 ********************************************************************* */
251 static int smbus_writebyte(int chan,int slaveaddr,int devaddr,int b)
253 uintptr_t reg;
254 int err;
255 int64_t timer;
258 * Make sure the bus is idle (probably should
259 * ignore error here)
262 if (smbus_waitready(chan) < 0) return -1;
265 * Write the device address to the controller. There are two
266 * parts, the high part goes in the "CMD" field, and the
267 * low part is the data field.
270 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD));
271 SBWRITECSR(reg,devaddr);
274 * Write the data to the controller
277 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
278 SBWRITECSR(reg,b);
281 * Start the command. Keep pounding on the device until it
282 * submits or the timer expires, whichever comes first. The
283 * datasheet says writes can take up to 10ms, so we'll give it 500.
286 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START));
287 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR2BYTE) | slaveaddr);
290 * Wait till the SMBus interface is done
293 err = smbus_waitready(chan);
294 if (err < 0) return err;
297 * Pound on the device with a current address read
298 * to poll for the write complete
301 TIMER_SET(timer,50);
302 err = -1;
304 while (!TIMER_EXPIRED(timer)) {
305 POLL();
307 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_RD1BYTE) | slaveaddr);
309 err = smbus_waitready(chan);
310 if (err == 0) break;
313 return err;
316 /* *********************************************************************
317 * sb1250_at24c02eeprom_probe(drv,a,b,ptr)
319 * Probe routine for this driver. This routine creates the
320 * local device context and attaches it to the driver list
321 * within CFE.
323 * Input parameters:
324 * drv - driver handle
325 * a,b - probe hints (longs)
326 * ptr - probe hint (pointer)
328 * Return value:
329 * nothing
330 ********************************************************************* */
332 static void sb1250_at24c02eeprom_probe(cfe_driver_t *drv,
333 unsigned long probe_a, unsigned long probe_b,
334 void *probe_ptr)
336 sb1250_at24c02eeprom_t *softc;
337 char descr[80];
339 softc = (sb1250_at24c02eeprom_t *) KMALLOC(sizeof(sb1250_at24c02eeprom_t),0);
342 * Probe_a is the SMBus channel number
343 * Probe_b is the SMBus device offset
344 * Probe_ptr is unused.
347 softc->smbus_channel = (int)probe_a;
348 softc->smbus_address = (int)probe_b;
349 softc->env_offset = 0;
350 softc->env_size = AT24C02_EEPROM_SIZE;
352 xsprintf(descr,"%s on SMBus channel %d dev 0x%02X",
353 drv->drv_description,(int)probe_a,(int)probe_b);
354 cfe_attach(drv,softc,NULL,descr);
359 /* *********************************************************************
360 * sb1250_at24c02eeprom_open(ctx)
362 * Open this device.
364 * Input parameters:
365 * ctx - device context (can obtain our softc here)
367 * Return value:
368 * 0 if ok
369 * else error code
370 ********************************************************************* */
372 static int sb1250_at24c02eeprom_open(cfe_devctx_t *ctx)
374 sb1250_at24c02eeprom_t *softc = ctx->dev_softc;
375 int b;
377 smbus_init(softc->smbus_channel);
379 b = smbus_readbyte(softc->smbus_channel,
380 softc->smbus_address,
383 return (b < 0) ? -1 : 0;
386 /* *********************************************************************
387 * sb1250_at24c02eeprom_read(ctx,buffer)
389 * Read bytes from the device.
391 * Input parameters:
392 * ctx - device context (can obtain our softc here)
393 * buffer - buffer descriptor (target buffer, length, offset)
395 * Return value:
396 * number of bytes read
397 * -1 if an error occured
398 ********************************************************************* */
400 static int sb1250_at24c02eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
402 sb1250_at24c02eeprom_t *softc = ctx->dev_softc;
403 unsigned char *bptr;
404 int blen;
405 int idx;
406 int b = 0;
408 bptr = buffer->buf_ptr;
409 blen = buffer->buf_length;
411 if ((buffer->buf_offset + blen) > AT24C02_EEPROM_SIZE) return -1;
413 idx = (int) buffer->buf_offset;
415 while (blen > 0) {
416 b = smbus_readbyte(softc->smbus_channel,
417 softc->smbus_address,
418 idx);
419 if (b < 0) break;
420 *bptr++ = (unsigned char) b;
421 blen--;
422 idx++;
425 buffer->buf_retlen = bptr - buffer->buf_ptr;
426 return (b < 0) ? -1 : 0;
429 /* *********************************************************************
430 * sb1250_at24c02eeprom_inpstat(ctx,inpstat)
432 * Test input (read) status for the device
434 * Input parameters:
435 * ctx - device context (can obtain our softc here)
436 * inpstat - input status descriptor to receive value
438 * Return value:
439 * 0 if ok
440 * -1 if an error occured
441 ********************************************************************* */
443 static int sb1250_at24c02eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
445 inpstat->inp_status = 1;
447 return 0;
450 /* *********************************************************************
451 * sb1250_at24c02eeprom_write(ctx,buffer)
453 * Write bytes from the device.
455 * Input parameters:
456 * ctx - device context (can obtain our softc here)
457 * buffer - buffer descriptor (target buffer, length, offset)
459 * Return value:
460 * number of bytes read
461 * -1 if an error occured
462 ********************************************************************* */
464 static int sb1250_at24c02eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
466 sb1250_at24c02eeprom_t *softc = ctx->dev_softc;
467 unsigned char *bptr;
468 int blen;
469 int idx;
470 int b = 0;
472 bptr = buffer->buf_ptr;
473 blen = buffer->buf_length;
475 if ((buffer->buf_offset + blen) > AT24C02_EEPROM_SIZE) return -1;
477 idx = (int) buffer->buf_offset;
479 while (blen > 0) {
480 b = *bptr++;
481 b = smbus_writebyte(softc->smbus_channel,
482 softc->smbus_address,
483 idx,
485 if (b < 0) break;
486 blen--;
487 idx++;
490 buffer->buf_retlen = bptr - buffer->buf_ptr;
491 return (b < 0) ? -1 : 0;
494 /* *********************************************************************
495 * sb1250_at24c02eeprom_ioctl(ctx,buffer)
497 * Perform miscellaneous I/O control operations on the device.
499 * Input parameters:
500 * ctx - device context (can obtain our softc here)
501 * buffer - buffer descriptor (target buffer, length, offset)
503 * Return value:
504 * number of bytes read
505 * -1 if an error occured
506 ********************************************************************* */
508 static int sb1250_at24c02eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
510 sb1250_at24c02eeprom_t *softc = ctx->dev_softc;
511 nvram_info_t *info;
513 switch ((int)buffer->buf_ioctlcmd) {
514 case IOCTL_NVRAM_GETINFO:
515 info = (nvram_info_t *) buffer->buf_ptr;
516 if (buffer->buf_length != sizeof(nvram_info_t)) return -1;
517 info->nvram_offset = softc->env_offset;
518 info->nvram_size = softc->env_size;
519 info->nvram_eraseflg = FALSE;
520 buffer->buf_retlen = sizeof(nvram_info_t);
521 return 0;
522 default:
523 return -1;
527 /* *********************************************************************
528 * sb1250_at24c02eeprom_close(ctx,buffer)
530 * Close the device.
532 * Input parameters:
533 * ctx - device context (can obtain our softc here)
535 * Return value:
536 * 0 if ok
537 * -1 if an error occured
538 ********************************************************************* */
540 static int sb1250_at24c02eeprom_close(cfe_devctx_t *ctx)
542 return 0;