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_x1240eeprom.c
blob582c363054a0a770af4da475d2aed790ecf7732d
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Xicor RTC/EEPROM driver File: dev_sb1250_x1240eeprom.c
5 *
6 * This module contains a CFE driver for a Xicor X1240 SMBus
7 * real-time-clock & EEPROM module. The only functionality
8 * we currently export is the EEPROM, for use as environment
9 * storage.
11 * Author: Mitch Lichtenberg (mpl@broadcom.com)
13 *********************************************************************
15 * Copyright 2000,2001,2002,2003
16 * Broadcom Corporation. All rights reserved.
18 * This software is furnished under license and may be used and
19 * copied only in accordance with the following terms and
20 * conditions. Subject to these conditions, you may download,
21 * copy, install, use, modify and distribute modified or unmodified
22 * copies of this software in source and/or binary form. No title
23 * or ownership is transferred hereby.
25 * 1) Any source code used, modified or distributed must reproduce
26 * and retain this copyright notice and list of conditions
27 * as they appear in the source file.
29 * 2) No right is granted to use any trade name, trademark, or
30 * logo of Broadcom Corporation. The "Broadcom Corporation"
31 * name may not be used to endorse or promote products derived
32 * from this software without the prior written permission of
33 * Broadcom Corporation.
35 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
39 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
40 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
46 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
47 * THE POSSIBILITY OF SUCH DAMAGE.
48 ********************************************************************* */
51 #include "sbmips.h"
52 #include "lib_types.h"
53 #include "lib_malloc.h"
54 #include "lib_printf.h"
56 #include "cfe_iocb.h"
57 #include "cfe_device.h"
58 #include "cfe_ioctl.h"
59 #include "cfe_timer.h"
61 #include "sb1250_defs.h"
62 #include "sb1250_regs.h"
63 #include "sb1250_smbus.h"
66 /* *********************************************************************
67 * Xicor X1241 RTC constants
68 ********************************************************************* */
71 * Register bits
74 #define X1241REG_SR_BAT 0x80 /* currently on battery power */
75 #define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
76 #define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
77 #define X1241REG_SR_RTCF 0x01 /* clock failed */
78 #define X1241REG_BL_BP2 0x80 /* block protect 2 */
79 #define X1241REG_BL_BP1 0x40 /* block protect 1 */
80 #define X1241REG_BL_BP0 0x20 /* block protect 0 */
81 #define X1241REG_BL_WD1 0x10
82 #define X1241REG_BL_WD0 0x08
83 #define X1241REG_HR_MIL 0x80 /* military time format */
86 * Register numbers
89 #define X1241REG_BL 0x10 /* block protect bits */
90 #define X1241REG_INT 0x11 /* */
91 #define X1241REG_SC 0x30 /* Seconds */
92 #define X1241REG_MN 0x31 /* Minutes */
93 #define X1241REG_HR 0x32 /* Hours */
94 #define X1241REG_DT 0x33 /* Day of month */
95 #define X1241REG_MO 0x34 /* Month */
96 #define X1241REG_YR 0x35 /* Year */
97 #define X1241REG_DW 0x36 /* Day of Week */
98 #define X1241REG_Y2K 0x37 /* Year 2K */
99 #define X1241REG_SR 0x3F /* Status register */
101 #define X1241_CCR_ADDRESS 0x6F
102 #define X1241_ARRAY_ADDRESS 0x57
104 #define X1241_EEPROM_SIZE 2048
106 /* *********************************************************************
107 * Forward Declarations
108 ********************************************************************* */
110 static void sb1250_x1240eeprom_probe(cfe_driver_t *drv,
111 unsigned long probe_a, unsigned long probe_b,
112 void *probe_ptr);
115 static int sb1250_x1240eeprom_open(cfe_devctx_t *ctx);
116 static int sb1250_x1240eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
117 static int sb1250_x1240eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
118 static int sb1250_x1240eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
119 static int sb1250_x1240eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
120 static int sb1250_x1240eeprom_close(cfe_devctx_t *ctx);
122 /* *********************************************************************
123 * Dispatch tables
124 ********************************************************************* */
126 const static cfe_devdisp_t sb1250_x1240eeprom_dispatch = {
127 sb1250_x1240eeprom_open,
128 sb1250_x1240eeprom_read,
129 sb1250_x1240eeprom_inpstat,
130 sb1250_x1240eeprom_write,
131 sb1250_x1240eeprom_ioctl,
132 sb1250_x1240eeprom_close,
133 NULL,
134 NULL
137 const cfe_driver_t sb1250_x1240eeprom = {
138 "Xicor X1241 EEPROM",
139 "eeprom",
140 CFE_DEV_NVRAM,
141 &sb1250_x1240eeprom_dispatch,
142 sb1250_x1240eeprom_probe
145 typedef struct sb1250_x1240eeprom_s {
146 int smbus_channel;
147 int env_offset;
148 int env_size;
149 unsigned char data[X1241_EEPROM_SIZE];
150 } sb1250_x1240eeprom_t;
153 /* *********************************************************************
154 * smbus_init(chan)
156 * Initialize the specified SMBus channel
158 * Input parameters:
159 * chan - channel # (0 or 1)
161 * Return value:
162 * nothing
163 ********************************************************************* */
165 static void smbus_init(int chan)
167 uintptr_t reg;
169 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_FREQ));
171 SBWRITECSR(reg,K_SMB_FREQ_100KHZ); /* 100KHz clock */
173 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CONTROL));
175 SBWRITECSR(reg,0); /* not in direct mode, no interrupts, will poll */
179 /* *********************************************************************
180 * smbus_waitready(chan)
182 * Wait until the SMBus channel is ready. We simply poll
183 * the busy bit until it clears.
185 * Input parameters:
186 * chan - channel (0 or 1)
188 * Return value:
189 * nothing
190 ********************************************************************* */
191 static int smbus_waitready(int chan)
193 uintptr_t reg;
194 uint64_t status;
196 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_STATUS));
198 for (;;) {
199 status = SBREADCSR(reg);
200 if (status & M_SMB_BUSY) continue;
201 break;
204 if (status & M_SMB_ERROR) {
206 SBWRITECSR(reg,(status & M_SMB_ERROR));
207 return -1;
209 return 0;
212 /* *********************************************************************
213 * smbus_readrtc(chan,slaveaddr,devaddr)
215 * Read a byte from the chip. The 'slaveaddr' parameter determines
216 * whether we're reading from the RTC section or the EEPROM section.
218 * Input parameters:
219 * chan - SMBus channel
220 * slaveaddr - SMBus slave address
221 * devaddr - byte with in the X1240 device to read
223 * Return value:
224 * 0 if ok
225 * else -1
226 ********************************************************************* */
228 static int smbus_readrtc(int chan,int slaveaddr,int devaddr)
230 uintptr_t reg;
231 int err;
234 * Make sure the bus is idle (probably should
235 * ignore error here)
238 if (smbus_waitready(chan) < 0) return -1;
241 * Write the device address to the controller. There are two
242 * parts, the high part goes in the "CMD" field, and the
243 * low part is the data field.
246 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD));
247 SBWRITECSR(reg,((devaddr >> 8) & 0x7));
250 * Write the data to the controller
253 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
254 SBWRITECSR(reg,((devaddr & 0xFF) & 0xFF));
257 * Start the command
260 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START));
261 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR2BYTE) | slaveaddr);
264 * Wait till done
267 err = smbus_waitready(chan);
268 if (err < 0) return err;
271 * Read the data byte
274 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_RD1BYTE) | slaveaddr);
276 err = smbus_waitready(chan);
277 if (err < 0) return err;
279 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
280 err = SBREADCSR(reg);
282 return (err & 0xFF);
285 /* *********************************************************************
286 * smbus_writertc(chan,slaveaddr,devaddr,b)
288 * write a byte from the chip. The 'slaveaddr' parameter determines
289 * whethe we're writing to the RTC section or the EEPROM section.
291 * Input parameters:
292 * chan - SMBus channel
293 * slaveaddr - SMBus slave address
294 * devaddr - byte with in the X1240 device to read
295 * b - byte to write
297 * Return value:
298 * 0 if ok
299 * else -1
300 ********************************************************************* */
303 static int smbus_writertc(int chan,int slaveaddr,int devaddr,int b)
305 uintptr_t reg;
306 int err;
307 int64_t timer;
310 * Make sure the bus is idle (probably should
311 * ignore error here)
314 if (smbus_waitready(chan) < 0) return -1;
317 * Write the device address to the controller. There are two
318 * parts, the high part goes in the "CMD" field, and the
319 * low part is the data field.
322 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD));
323 SBWRITECSR(reg,((devaddr >> 8) & 0x7));
326 * Write the data to the controller
329 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
330 SBWRITECSR(reg,((devaddr & 0xFF) | ((b & 0xFF) << 8)));
333 * Start the command. Keep pounding on the device until it
334 * submits or the timer expires, whichever comes first. The
335 * datasheet says writes can take up to 10ms, so we'll give it 500.
338 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START));
339 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR3BYTE) | slaveaddr);
342 * Wait till the SMBus interface is done
345 err = smbus_waitready(chan);
346 if (err < 0) return err;
349 * Pound on the device with a current address read
350 * to poll for the write complete
353 TIMER_SET(timer,50);
354 err = -1;
356 while (!TIMER_EXPIRED(timer)) {
357 POLL();
359 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_RD1BYTE) | slaveaddr);
361 err = smbus_waitready(chan);
362 if (err == 0) break;
365 return err;
369 /* *********************************************************************
370 * sb1250_x1240eeprom_probe(drv,a,b,ptr)
372 * Probe routine for this driver. This routine creates the
373 * local device context and attaches it to the driver list
374 * within CFE.
376 * Input parameters:
377 * drv - driver handle
378 * a,b - probe hints (longs)
379 * ptr - probe hint (pointer)
381 * Return value:
382 * nothing
383 ********************************************************************* */
385 static void sb1250_x1240eeprom_probe(cfe_driver_t *drv,
386 unsigned long probe_a, unsigned long probe_b,
387 void *probe_ptr)
389 sb1250_x1240eeprom_t *softc;
390 char descr[80];
392 softc = (sb1250_x1240eeprom_t *) KMALLOC(sizeof(sb1250_x1240eeprom_t),0);
395 * Probe_a is the SMBus channel number
396 * Probe_b is the SMBus device offset
397 * Probe_ptr is unused.
400 softc->smbus_channel = (int)probe_a;
401 softc->env_offset = 0;
402 softc->env_size = X1241_EEPROM_SIZE;
404 xsprintf(descr,"%s on SMBus channel %d",
405 drv->drv_description,probe_a);
406 cfe_attach(drv,softc,NULL,descr);
411 /* *********************************************************************
412 * sb1250_x1240eeprom_open(ctx)
414 * Open this device. For the X1240, we do a quick test
415 * read to be sure the device is out there.
417 * Input parameters:
418 * ctx - device context (can obtain our softc here)
420 * Return value:
421 * 0 if ok
422 * else error code
423 ********************************************************************* */
425 static int sb1250_x1240eeprom_open(cfe_devctx_t *ctx)
427 sb1250_x1240eeprom_t *softc = ctx->dev_softc;
428 int b;
429 int64_t timer;
432 * Try to read byte 0 from the device. If it does not
433 * respond, fail the open. We may need to do this for
434 * up to 300ms in case the X1240 is busy wiggling its
435 * RESET line.
438 smbus_init(softc->smbus_channel);
440 TIMER_SET(timer,300);
441 while (!TIMER_EXPIRED(timer)) {
442 POLL();
443 b = smbus_readrtc(softc->smbus_channel,
444 X1241_ARRAY_ADDRESS,
446 if (b >= 0) break; /* read is ok */
450 * See if the watchdog is enabled. If it is, turn it off.
453 b = smbus_readrtc(softc->smbus_channel,
454 X1241_CCR_ADDRESS,
455 X1241REG_BL);
457 if (b != (X1241REG_BL_WD1 | X1241REG_BL_WD0)) {
459 smbus_writertc(softc->smbus_channel,
460 X1241_CCR_ADDRESS,
461 X1241REG_SR,
462 X1241REG_SR_WEL);
464 smbus_writertc(softc->smbus_channel,
465 X1241_CCR_ADDRESS,
466 X1241REG_SR,
467 X1241REG_SR_WEL | X1241REG_SR_RWEL);
469 smbus_writertc(softc->smbus_channel,
470 X1241_CCR_ADDRESS,
471 X1241REG_BL,
472 (X1241REG_BL_WD1 | X1241REG_BL_WD0));
474 smbus_writertc(softc->smbus_channel,
475 X1241_CCR_ADDRESS,
476 X1241REG_SR,
482 return (b < 0) ? -1 : 0;
485 /* *********************************************************************
486 * sb1250_x1240eeprom_read(ctx,buffer)
488 * Read bytes from the device.
490 * Input parameters:
491 * ctx - device context (can obtain our softc here)
492 * buffer - buffer descriptor (target buffer, length, offset)
494 * Return value:
495 * number of bytes read
496 * -1 if an error occured
497 ********************************************************************* */
499 static int sb1250_x1240eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
501 sb1250_x1240eeprom_t *softc = ctx->dev_softc;
502 unsigned char *bptr;
503 int blen;
504 int idx;
505 int b = 0;
507 bptr = buffer->buf_ptr;
508 blen = buffer->buf_length;
510 if ((buffer->buf_offset + blen) > X1241_EEPROM_SIZE) return -1;
512 idx = (int) buffer->buf_offset;
514 while (blen > 0) {
515 b = smbus_readrtc(softc->smbus_channel,
516 X1241_ARRAY_ADDRESS,
517 idx);
518 if (b < 0) break;
519 *bptr++ = (unsigned char) b;
520 blen--;
521 idx++;
524 buffer->buf_retlen = bptr - buffer->buf_ptr;
525 return (b < 0) ? -1 : 0;
528 /* *********************************************************************
529 * sb1250_x1240eeprom_inpstat(ctx,inpstat)
531 * Test input (read) status for the device
533 * Input parameters:
534 * ctx - device context (can obtain our softc here)
535 * inpstat - input status descriptor to receive value
537 * Return value:
538 * 0 if ok
539 * -1 if an error occured
540 ********************************************************************* */
542 static int sb1250_x1240eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
544 inpstat->inp_status = 1;
546 return 0;
549 /* *********************************************************************
550 * sb1250_x1240eeprom_write(ctx,buffer)
552 * Write bytes from the device.
554 * Input parameters:
555 * ctx - device context (can obtain our softc here)
556 * buffer - buffer descriptor (target buffer, length, offset)
558 * Return value:
559 * number of bytes read
560 * -1 if an error occured
561 ********************************************************************* */
563 static int sb1250_x1240eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
565 sb1250_x1240eeprom_t *softc = ctx->dev_softc;
566 unsigned char *bptr;
567 int blen;
568 int idx;
569 int b = 0;
571 bptr = buffer->buf_ptr;
572 blen = buffer->buf_length;
574 if ((buffer->buf_offset + blen) > X1241_EEPROM_SIZE) return -1;
576 idx = (int) buffer->buf_offset;
578 smbus_writertc(softc->smbus_channel,
579 X1241_CCR_ADDRESS,
580 X1241REG_SR,
581 X1241REG_SR_WEL);
584 while (blen > 0) {
585 b = *bptr++;
586 b = smbus_writertc(softc->smbus_channel,
587 X1241_ARRAY_ADDRESS,
588 idx,
590 if (b < 0) break;
591 blen--;
592 idx++;
595 smbus_writertc(softc->smbus_channel,
596 X1241_CCR_ADDRESS,
597 X1241REG_SR,
600 buffer->buf_retlen = bptr - buffer->buf_ptr;
601 return (b < 0) ? -1 : 0;
604 /* *********************************************************************
605 * sb1250_x1240eeprom_ioctl(ctx,buffer)
607 * Perform miscellaneous I/O control operations on the device.
609 * Input parameters:
610 * ctx - device context (can obtain our softc here)
611 * buffer - buffer descriptor (target buffer, length, offset)
613 * Return value:
614 * number of bytes read
615 * -1 if an error occured
616 ********************************************************************* */
618 static int sb1250_x1240eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
620 sb1250_x1240eeprom_t *softc = ctx->dev_softc;
621 nvram_info_t *info;
623 switch ((int)buffer->buf_ioctlcmd) {
624 case IOCTL_NVRAM_GETINFO:
625 info = (nvram_info_t *) buffer->buf_ptr;
626 if (buffer->buf_length != sizeof(nvram_info_t)) return -1;
627 info->nvram_offset = softc->env_offset;
628 info->nvram_size = softc->env_size;
629 info->nvram_eraseflg = FALSE;
630 buffer->buf_retlen = sizeof(nvram_info_t);
631 return 0;
632 default:
633 return -1;
637 /* *********************************************************************
638 * sb1250_x1240eeprom_close(ctx,buffer)
640 * Close the device.
642 * Input parameters:
643 * ctx - device context (can obtain our softc here)
645 * Return value:
646 * 0 if ok
647 * -1 if an error occured
648 ********************************************************************* */
650 static int sb1250_x1240eeprom_close(cfe_devctx_t *ctx)
652 return 0;