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_x1241clock.c
blob9d6519a8b7a14df6b8c4d1f3b705ee7f3d664120
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Xicor RTC driver File: dev_sb1250_x1241clock.c
5 *
6 * This module contains a CFE driver for a Xicor X1241 SMBus
7 * real-time-clock.
8 *
9 * Author: Mitch Lichtenberg (mpl@broadcom.com) and Binh Vo
11 *********************************************************************
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
16 * This software is furnished under license and may be used and
17 * copied only in accordance with the following terms and
18 * conditions. Subject to these conditions, you may download,
19 * copy, install, use, modify and distribute modified or unmodified
20 * copies of this software in source and/or binary form. No title
21 * or ownership is transferred hereby.
23 * 1) Any source code used, modified or distributed must reproduce
24 * and retain this copyright notice and list of conditions
25 * as they appear in the source file.
27 * 2) No right is granted to use any trade name, trademark, or
28 * logo of Broadcom Corporation. The "Broadcom Corporation"
29 * name may not be used to endorse or promote products derived
30 * from this software without the prior written permission of
31 * Broadcom Corporation.
33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGE.
46 ********************************************************************* */
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 * Constants
65 ********************************************************************* */
68 * Register bits
71 #define X1241REG_SR_BAT 0x80 /* currently on battery power */
72 #define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
73 #define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
74 #define X1241REG_SR_RTCF 0x01 /* clock failed */
75 #define X1241REG_BL_BP2 0x80 /* block protect 2 */
76 #define X1241REG_BL_BP1 0x40 /* block protect 1 */
77 #define X1241REG_BL_BP0 0x20 /* block protect 0 */
78 #define X1241REG_BL_WD1 0x10
79 #define X1241REG_BL_WD0 0x08
80 #define X1241REG_HR_MIL 0x80 /* military time format */
83 * Register numbers
86 #define X1241REG_BL 0x10 /* block protect bits */
87 #define X1241REG_INT 0x11 /* */
88 #define X1241REG_SC 0x30 /* Seconds */
89 #define X1241REG_MN 0x31 /* Minutes */
90 #define X1241REG_HR 0x32 /* Hours */
91 #define X1241REG_DT 0x33 /* Day of month */
92 #define X1241REG_MO 0x34 /* Month */
93 #define X1241REG_YR 0x35 /* Year */
94 #define X1241REG_DW 0x36 /* Day of Week */
95 #define X1241REG_Y2K 0x37 /* Year 2K */
96 #define X1241REG_SR 0x3F /* Status register */
98 #define X1241_CCR_ADDRESS 0x6F
99 #define X1241_ARRAY_ADDRESS 0x57
101 #define X1241_EEPROM_SIZE 2048
103 #define BCD(x) (((x) % 10) + (((x) / 10) << 4))
104 #define SET_TIME 0x00
105 #define SET_DATE 0x01
107 /* *********************************************************************
108 * Forward declarations
109 ********************************************************************* */
111 static void x1241_clock_probe(cfe_driver_t *drv,
112 unsigned long probe_a, unsigned long probe_b,
113 void *probe_ptr);
115 static int x1241_clock_open(cfe_devctx_t *ctx);
116 static int x1241_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
117 static int x1241_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
118 static int x1241_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
119 static int x1241_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
120 static int x1241_clock_close(cfe_devctx_t *ctx);
123 /* *********************************************************************
124 * Device dispatch
125 ********************************************************************* */
127 const static cfe_devdisp_t x1241_clock_dispatch = {
128 x1241_clock_open,
129 x1241_clock_read,
130 x1241_clock_inpstat,
131 x1241_clock_write,
132 x1241_clock_ioctl,
133 x1241_clock_close,
134 NULL,
135 NULL
138 const cfe_driver_t x1241_clock = {
139 "Xicor X1241 RTC",
140 "clock",
141 CFE_DEV_CLOCK,
142 &x1241_clock_dispatch,
143 x1241_clock_probe
147 /* *********************************************************************
148 * Structures
149 ********************************************************************* */
150 typedef struct x1241_clock_s {
151 int smbus_channel;
152 } x1241_clock_t;
154 /* *********************************************************************
155 * time_smbus_init(chan)
157 * Initialize the specified SMBus channel for the temp sensor
159 * Input parameters:
160 * chan - channel # (0 or 1)
162 * Return value:
163 * nothing
164 ********************************************************************* */
166 static void time_smbus_init(int chan)
168 uintptr_t reg;
170 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_FREQ));
172 SBWRITECSR(reg,K_SMB_FREQ_100KHZ); /* 100KHz clock */
174 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CONTROL));
176 SBWRITECSR(reg,0); /* not in direct mode, no interrupts, will poll */
180 /* *********************************************************************
181 * time_waitready(chan)
183 * Wait until the SMBus channel is ready. We simply poll
184 * the busy bit until it clears.
186 * Input parameters:
187 * chan - channel (0 or 1)
189 * Return value:
190 * nothing
191 ********************************************************************* */
192 static int time_waitready(int chan)
194 uintptr_t reg;
195 uint64_t status;
197 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_STATUS));
199 for (;;) {
200 status = SBREADCSR(reg);
201 if (status & M_SMB_BUSY) continue;
202 break;
205 if (status & M_SMB_ERROR) {
207 SBWRITECSR(reg,(status & M_SMB_ERROR));
208 return -1;
210 return 0;
213 /* *********************************************************************
214 * time_readrtc(chan,slaveaddr,devaddr)
216 * Read a byte from the chip. The 'slaveaddr' parameter determines
217 * whether we're reading from the RTC section or the EEPROM section.
219 * Input parameters:
220 * chan - SMBus channel
221 * slaveaddr - SMBus slave address
222 * devaddr - byte with in the X1240 device to read
224 * Return value:
225 * 0 if ok
226 * else -1
227 ********************************************************************* */
229 static int time_readrtc(int chan,int slaveaddr,int devaddr)
231 uintptr_t reg;
232 int err;
235 * Make sure the bus is idle (probably should
236 * ignore error here)
239 if (time_waitready(chan) < 0) return -1;
242 * Write the device address to the controller. There are two
243 * parts, the high part goes in the "CMD" field, and the
244 * low part is the data field.
247 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD));
248 SBWRITECSR(reg,((devaddr >> 8) & 0x7));
251 * Write the data to the controller
254 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
255 SBWRITECSR(reg,((devaddr & 0xFF) & 0xFF));
258 * Start the command
261 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START));
262 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR2BYTE) | slaveaddr);
265 * Wait till done
268 err = time_waitready(chan);
269 if (err < 0) return err;
272 * Read the data byte
275 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_RD1BYTE) | slaveaddr);
277 err = time_waitready(chan);
278 if (err < 0) return err;
280 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
281 err = SBREADCSR(reg);
283 return (err & 0xFF);
286 /* *********************************************************************
287 * time_writertc(chan,slaveaddr,devaddr,b)
289 * write a byte from the chip. The 'slaveaddr' parameter determines
290 * whethe we're writing to the RTC section or the EEPROM section.
292 * Input parameters:
293 * chan - SMBus channel
294 * slaveaddr - SMBus slave address
295 * devaddr - byte with in the X1240 device to read
296 * b - byte to write
298 * Return value:
299 * 0 if ok
300 * else -1
301 ********************************************************************* */
303 static int time_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 (time_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 = time_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 = time_waitready(chan);
362 if (err == 0) break;
365 return err;
369 /* *********************************************************************
370 * x1241_clock_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 x1241_clock_probe(cfe_driver_t *drv,
386 unsigned long probe_a, unsigned long probe_b,
387 void *probe_ptr)
389 x1241_clock_t *softc;
390 char descr[80];
392 softc = (x1241_clock_t *) KMALLOC(sizeof(x1241_clock_t),0);
395 * Probe_a is the SMBus channel number
396 * Probe_b is unused.
397 * Probe_ptr is unused.
400 softc->smbus_channel = (int)probe_a;
402 xsprintf(descr,"%s on SMBus channel %d",
403 drv->drv_description,probe_a);
404 cfe_attach(drv,softc,NULL,descr);
409 /* *********************************************************************
410 * x1241_clock_open(ctx)
412 * Open this device. For the X1241, we do a quick test
413 * read to be sure the device is out there.
415 * Input parameters:
416 * ctx - device context (can obtain our softc here)
418 * Return value:
419 * 0 if ok
420 * else error code
421 ********************************************************************* */
423 static int x1241_clock_open(cfe_devctx_t *ctx)
425 x1241_clock_t *softc = ctx->dev_softc;
426 int b;
427 int64_t timer;
428 int chan = softc->smbus_channel;
431 * Try to read byte 0 from the device. If it does not
432 * respond, fail the open. We may need to do this for
433 * up to 300ms in case the X1241 is busy wiggling its
434 * RESET line.
437 time_smbus_init(chan);
439 TIMER_SET(timer,300);
440 while (!TIMER_EXPIRED(timer)) {
441 POLL();
442 b = time_readrtc(chan,X1241_CCR_ADDRESS,0);
443 if (b >= 0) break; /* read is ok */
447 * See if the watchdog is enabled. If it is, turn it off.
450 b = time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_BL);
452 if (b != (X1241REG_BL_WD1 | X1241REG_BL_WD0)) {
454 time_writertc(chan,
455 X1241_CCR_ADDRESS,
456 X1241REG_SR,
457 X1241REG_SR_WEL);
459 time_writertc(chan,
460 X1241_CCR_ADDRESS,
461 X1241REG_SR,
462 X1241REG_SR_WEL | X1241REG_SR_RWEL);
464 time_writertc(chan,
465 X1241_CCR_ADDRESS,
466 X1241REG_BL,
467 (X1241REG_BL_WD1 | X1241REG_BL_WD0));
469 time_writertc(chan,
470 X1241_CCR_ADDRESS,
471 X1241REG_SR,
475 return (b < 0) ? -1 : 0;
478 /* *********************************************************************
479 * x1241_clock_read(ctx,buffer)
481 * Read time/date from the RTC. Read a total of 8 bytes in this format:
482 * hour-minute-second-month-day-year1-year2
484 * Input parameters:
485 * ctx - device context (can obtain our softc here)
486 * buffer - buffer descriptor (target buffer, length, offset)
488 * Return value:
489 * number of bytes read
490 * -1 if an error occured
491 ********************************************************************* */
493 static int x1241_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
496 x1241_clock_t *softc = ctx->dev_softc;
497 uint8_t byte;
498 unsigned char *bptr;
499 int chan = softc->smbus_channel;
501 bptr = buffer->buf_ptr;
503 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_HR);
504 byte &= ~X1241REG_HR_MIL;
505 *bptr++ = (unsigned char) byte;
507 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_MN);
508 *bptr++ = (unsigned char) byte;
510 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_SC);
511 *bptr++ = (unsigned char) byte;
513 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_MO);
514 *bptr++ = (unsigned char) byte;
516 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_DT);
517 *bptr++ = (unsigned char) byte;
519 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_YR);
520 *bptr++ = (unsigned char) byte;
522 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_Y2K);
523 *bptr = (unsigned char) byte;
525 byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_SR);
527 /*Last byte is status of battery*/
528 if (byte & X1241REG_SR_RTCF)
530 printf("Warning: Battery has failed. Clock setting is not accurate.\n");
533 buffer->buf_retlen = 8;
534 return 0;
537 /* *********************************************************************
538 * x1241_clock_write(ctx,buffer)
540 * Write time/date to the RTC. Write in this format:
541 * hour-minute-second-month-day-year1-year2-(time/date flag)
543 * Input parameters:
544 * ctx - device context (can obtain our softc here)
545 * buffer - buffer descriptor (target buffer, length, offset)
547 * Return value:
548 * number of bytes written
549 * -1 if an error occured
550 ********************************************************************* */
552 static int x1241_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
554 x1241_clock_t *softc = ctx->dev_softc;
555 unsigned char *bptr;
556 uint8_t hr,min,sec;
557 uint8_t mo,day,yr,y2k;
558 uint8_t timeDateFlag;
559 int chan = softc->smbus_channel;
561 bptr = buffer->buf_ptr;
562 timeDateFlag = *(bptr + 7);
564 /* unlock writes to the CCR */
565 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_SR,X1241REG_SR_WEL);
566 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_SR,
567 X1241REG_SR_WEL | X1241REG_SR_RWEL);
569 /* write time or date */
570 if(timeDateFlag == SET_TIME) {
572 hr = (uint8_t) *bptr;
573 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_HR, BCD(hr) | X1241REG_HR_MIL);
575 min = (uint8_t) *(bptr+1);
576 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_MN, BCD(min) );
578 sec = (uint8_t) *(bptr+2);
579 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_SC, BCD(sec) );
581 buffer->buf_retlen = 3;
583 else if(timeDateFlag == SET_DATE) {
585 mo = (uint8_t) *(bptr+3);
586 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_MO, BCD(mo) );
588 day = (uint8_t) *(bptr+4);
589 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_DT, BCD(day) );
591 yr = (uint8_t) *(bptr+5);
592 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_YR, BCD(yr) );
594 y2k = (uint8_t) *(bptr+6);
595 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_Y2K, BCD(y2k) );
597 buffer->buf_retlen = 4;
599 else {
600 return -1;
603 /* lock writes again */
604 time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_SR,0);
606 return 0;
609 /* *********************************************************************
610 * x1241_clock_inpstat(ctx,inpstat)
612 * Test input (read) status for the device
614 * Input parameters:
615 * ctx - device context (can obtain our softc here)
616 * inpstat - input status descriptor to receive value
618 * Return value:
619 * 0 if ok
620 * -1 if an error occured
621 ********************************************************************* */
623 static int x1241_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
625 inpstat->inp_status = 1;
627 return 0;
630 /* *********************************************************************
631 * x1241_clock_ioctl(ctx,buffer)
633 * Perform miscellaneous I/O control operations on the device.
635 * Input parameters:
636 * ctx - device context (can obtain our softc here)
637 * buffer - buffer descriptor (target buffer, length, offset)
639 * Return value:
640 * number of bytes read
641 * -1 if an error occured
642 ********************************************************************* */
644 static int x1241_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
646 return 0;
649 /* *********************************************************************
650 * x1241_clock_close(ctx,buffer)
652 * Close the device.
654 * Input parameters:
655 * ctx - device context (can obtain our softc here)
657 * Return value:
658 * 0 if ok
659 * -1 if an error occured
660 ********************************************************************* */
662 static int x1241_clock_close(cfe_devctx_t *ctx)
664 return 0;