1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Xicor RTC driver File: dev_sb1250_x1241clock.c
6 * This module contains a CFE driver for a Xicor X1241 SMBus
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 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_malloc.h"
51 #include "lib_printf.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 /* *********************************************************************
65 ********************************************************************* */
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 */
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
,
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 /* *********************************************************************
125 ********************************************************************* */
127 const static cfe_devdisp_t x1241_clock_dispatch
= {
138 const cfe_driver_t x1241_clock
= {
142 &x1241_clock_dispatch
,
147 /* *********************************************************************
149 ********************************************************************* */
150 typedef struct x1241_clock_s
{
154 /* *********************************************************************
155 * time_smbus_init(chan)
157 * Initialize the specified SMBus channel for the temp sensor
160 * chan - channel # (0 or 1)
164 ********************************************************************* */
166 static void time_smbus_init(int chan
)
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.
187 * chan - channel (0 or 1)
191 ********************************************************************* */
192 static int time_waitready(int chan
)
197 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_STATUS
));
200 status
= SBREADCSR(reg
);
201 if (status
& M_SMB_BUSY
) continue;
205 if (status
& M_SMB_ERROR
) {
207 SBWRITECSR(reg
,(status
& M_SMB_ERROR
));
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.
220 * chan - SMBus channel
221 * slaveaddr - SMBus slave address
222 * devaddr - byte with in the X1240 device to read
227 ********************************************************************* */
229 static int time_readrtc(int chan
,int slaveaddr
,int devaddr
)
235 * Make sure the bus is idle (probably should
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));
261 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
262 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_WR2BYTE
) | slaveaddr
);
268 err
= time_waitready(chan
);
269 if (err
< 0) return err
;
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
);
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.
293 * chan - SMBus channel
294 * slaveaddr - SMBus slave address
295 * devaddr - byte with in the X1240 device to read
301 ********************************************************************* */
303 static int time_writertc(int chan
,int slaveaddr
,int devaddr
,int b
)
310 * Make sure the bus is idle (probably should
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
356 while (!TIMER_EXPIRED(timer
)) {
359 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_RD1BYTE
) | slaveaddr
);
361 err
= time_waitready(chan
);
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
377 * drv - driver handle
378 * a,b - probe hints (longs)
379 * ptr - probe hint (pointer)
383 ********************************************************************* */
385 static void x1241_clock_probe(cfe_driver_t
*drv
,
386 unsigned long probe_a
, unsigned long probe_b
,
389 x1241_clock_t
*softc
;
392 softc
= (x1241_clock_t
*) KMALLOC(sizeof(x1241_clock_t
),0);
395 * Probe_a is the SMBus channel number
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.
416 * ctx - device context (can obtain our softc here)
421 ********************************************************************* */
423 static int x1241_clock_open(cfe_devctx_t
*ctx
)
425 x1241_clock_t
*softc
= ctx
->dev_softc
;
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
437 time_smbus_init(chan
);
439 TIMER_SET(timer
,300);
440 while (!TIMER_EXPIRED(timer
)) {
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
)) {
462 X1241REG_SR_WEL
| X1241REG_SR_RWEL
);
467 (X1241REG_BL_WD1
| X1241REG_BL_WD0
));
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
485 * ctx - device context (can obtain our softc here)
486 * buffer - buffer descriptor (target buffer, length, offset)
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
;
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;
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)
544 * ctx - device context (can obtain our softc here)
545 * buffer - buffer descriptor (target buffer, length, offset)
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
;
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;
603 /* lock writes again */
604 time_writertc(chan
,X1241_CCR_ADDRESS
,X1241REG_SR
,0);
609 /* *********************************************************************
610 * x1241_clock_inpstat(ctx,inpstat)
612 * Test input (read) status for the device
615 * ctx - device context (can obtain our softc here)
616 * inpstat - input status descriptor to receive value
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;
630 /* *********************************************************************
631 * x1241_clock_ioctl(ctx,buffer)
633 * Perform miscellaneous I/O control operations on the device.
636 * ctx - device context (can obtain our softc here)
637 * buffer - buffer descriptor (target buffer, length, offset)
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
)
649 /* *********************************************************************
650 * x1241_clock_close(ctx,buffer)
655 * ctx - device context (can obtain our softc here)
659 * -1 if an error occured
660 ********************************************************************* */
662 static int x1241_clock_close(cfe_devctx_t
*ctx
)