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
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003
14    *  Broadcom Corporation. All rights reserved.
15    *
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.
22    *
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.
26    *
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.
32    *
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    ********************************************************************* */
47
48#include "sbmips.h"
49#include "lib_types.h"
50#include "lib_malloc.h"
51#include "lib_printf.h"
52
53#include "cfe_iocb.h"
54#include "cfe_device.h"
55#include "cfe_ioctl.h"
56#include "cfe_timer.h"
57
58#include "sb1250_defs.h"
59#include "sb1250_regs.h"
60#include "sb1250_smbus.h"
61
62
63/*  *********************************************************************
64    *  Constants
65    ********************************************************************* */
66
67/*
68 * Register bits
69 */
70
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 */
81
82/*
83 * Register numbers
84 */
85
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 */
97
98#define X1241_CCR_ADDRESS	0x6F
99#define X1241_ARRAY_ADDRESS	0x57
100
101#define X1241_EEPROM_SIZE 2048
102
103#define BCD(x) (((x) % 10) + (((x) / 10) << 4))
104#define SET_TIME	0x00
105#define SET_DATE	0x01
106
107/*  *********************************************************************
108    *  Forward declarations
109    ********************************************************************* */
110
111static void x1241_clock_probe(cfe_driver_t *drv,
112			      unsigned long probe_a, unsigned long probe_b,
113			      void *probe_ptr);
114
115static int x1241_clock_open(cfe_devctx_t *ctx);
116static int x1241_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
117static int x1241_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
118static int x1241_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
119static int x1241_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
120static int x1241_clock_close(cfe_devctx_t *ctx);
121
122
123/*  *********************************************************************
124    *  Device dispatch
125    ********************************************************************* */
126
127const 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
136};
137
138const cfe_driver_t x1241_clock = {
139  "Xicor X1241 RTC",
140  "clock",
141  CFE_DEV_CLOCK,
142  &x1241_clock_dispatch,
143  x1241_clock_probe
144};
145
146
147/*  *********************************************************************
148    *  Structures
149    ********************************************************************* */
150typedef struct x1241_clock_s {
151  int smbus_channel;
152} x1241_clock_t;
153
154/*  *********************************************************************
155    *  time_smbus_init(chan)
156    *
157    *  Initialize the specified SMBus channel for the temp sensor
158    *
159    *  Input parameters:
160    *  	   chan - channel # (0 or 1)
161    *
162    *  Return value:
163    *  	   nothing
164    ********************************************************************* */
165
166static void time_smbus_init(int chan)
167{
168    uintptr_t reg;
169
170    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_FREQ));
171
172    SBWRITECSR(reg,K_SMB_FREQ_100KHZ);			/* 100KHz clock */
173
174    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CONTROL));
175
176    SBWRITECSR(reg,0);			/* not in direct mode, no interrupts, will poll */
177
178}
179
180/*  *********************************************************************
181    *  time_waitready(chan)
182    *
183    *  Wait until the SMBus channel is ready.  We simply poll
184    *  the busy bit until it clears.
185    *
186    *  Input parameters:
187    *  	   chan - channel (0 or 1)
188    *
189    *  Return value:
190    *      nothing
191    ********************************************************************* */
192static int time_waitready(int chan)
193{
194    uintptr_t reg;
195    uint64_t status;
196
197    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_STATUS));
198
199    for (;;) {
200	status = SBREADCSR(reg);
201	if (status & M_SMB_BUSY) continue;
202	break;
203	}
204
205    if (status & M_SMB_ERROR) {
206
207	SBWRITECSR(reg,(status & M_SMB_ERROR));
208	return -1;
209	}
210    return 0;
211}
212
213/*  *********************************************************************
214    *  time_readrtc(chan,slaveaddr,devaddr)
215    *
216    *  Read a byte from the chip.  The 'slaveaddr' parameter determines
217    *  whether we're reading from the RTC section or the EEPROM section.
218    *
219    *  Input parameters:
220    *  	   chan - SMBus channel
221    *  	   slaveaddr -  SMBus slave address
222    *  	   devaddr - byte with in the X1240 device to read
223    *
224    *  Return value:
225    *  	   0 if ok
226    *  	   else -1
227    ********************************************************************* */
228
229static int time_readrtc(int chan,int slaveaddr,int devaddr)
230{
231    uintptr_t reg;
232    int err;
233
234    /*
235     * Make sure the bus is idle (probably should
236     * ignore error here)
237     */
238
239    if (time_waitready(chan) < 0) return -1;
240
241    /*
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.
245     */
246
247    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD));
248    SBWRITECSR(reg,((devaddr >> 8) & 0x7));
249
250    /*
251     * Write the data to the controller
252     */
253
254    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
255    SBWRITECSR(reg,((devaddr & 0xFF) & 0xFF));
256
257    /*
258     * Start the command
259     */
260
261    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START));
262    SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR2BYTE) | slaveaddr);
263
264    /*
265     * Wait till done
266     */
267
268    err = time_waitready(chan);
269    if (err < 0) return err;
270
271    /*
272     * Read the data byte
273     */
274
275    SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_RD1BYTE) | slaveaddr);
276
277    err = time_waitready(chan);
278    if (err < 0) return err;
279
280    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
281    err = SBREADCSR(reg);
282
283    return (err & 0xFF);
284}
285
286/*  *********************************************************************
287    *  time_writertc(chan,slaveaddr,devaddr,b)
288    *
289    *  write a byte from the chip.  The 'slaveaddr' parameter determines
290    *  whethe we're writing to the RTC section or the EEPROM section.
291    *
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
297    *
298    *  Return value:
299    *  	   0 if ok
300    *  	   else -1
301    ********************************************************************* */
302
303static int time_writertc(int chan,int slaveaddr,int devaddr,int b)
304{
305    uintptr_t reg;
306    int err;
307    int64_t timer;
308
309    /*
310     * Make sure the bus is idle (probably should
311     * ignore error here)
312     */
313
314    if (time_waitready(chan) < 0) return -1;
315
316    /*
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.
320     */
321
322    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD));
323    SBWRITECSR(reg,((devaddr >> 8) & 0x7));
324
325    /*
326     * Write the data to the controller
327     */
328
329    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA));
330    SBWRITECSR(reg,((devaddr & 0xFF) | ((b & 0xFF) << 8)));
331
332    /*
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.
336     */
337
338    reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START));
339    SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR3BYTE) | slaveaddr);
340
341    /*
342     * Wait till the SMBus interface is done
343     */
344
345    err = time_waitready(chan);
346    if (err < 0) return err;
347
348    /*
349     * Pound on the device with a current address read
350     * to poll for the write complete
351     */
352
353    TIMER_SET(timer,50);
354    err = -1;
355
356    while (!TIMER_EXPIRED(timer)) {
357	POLL();
358
359	SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_RD1BYTE) | slaveaddr);
360
361	err = time_waitready(chan);
362	if (err == 0) break;
363	}
364
365    return err;
366}
367
368
369/*  *********************************************************************
370    *  x1241_clock_probe(drv,a,b,ptr)
371    *
372    *  Probe routine for this driver.  This routine creates the
373    *  local device context and attaches it to the driver list
374    *  within CFE.
375    *
376    *  Input parameters:
377    *  	   drv - driver handle
378    *  	   a,b - probe hints (longs)
379    *  	   ptr - probe hint (pointer)
380    *
381    *  Return value:
382    *  	   nothing
383    ********************************************************************* */
384
385static void x1241_clock_probe(cfe_driver_t *drv,
386				     unsigned long probe_a, unsigned long probe_b,
387				     void *probe_ptr)
388{
389    x1241_clock_t *softc;
390    char descr[80];
391
392    softc = (x1241_clock_t *) KMALLOC(sizeof(x1241_clock_t),0);
393
394    /*
395     * Probe_a is the SMBus channel number
396     * Probe_b is unused.
397     * Probe_ptr is unused.
398     */
399
400    softc->smbus_channel = (int)probe_a;
401
402    xsprintf(descr,"%s on SMBus channel %d",
403	     drv->drv_description,probe_a);
404    cfe_attach(drv,softc,NULL,descr);
405}
406
407
408
409/*  *********************************************************************
410    *  x1241_clock_open(ctx)
411    *
412    *  Open this device.  For the X1241, we do a quick test
413    *  read to be sure the device is out there.
414    *
415    *  Input parameters:
416    *  	   ctx - device context (can obtain our softc here)
417    *
418    *  Return value:
419    *  	   0 if ok
420    *  	   else error code
421    ********************************************************************* */
422
423static int x1241_clock_open(cfe_devctx_t *ctx)
424{
425    x1241_clock_t *softc = ctx->dev_softc;
426    int b;
427    int64_t timer;
428    int chan = softc->smbus_channel;
429
430    /*
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.
435     */
436
437    time_smbus_init(chan);
438
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 */
444	}
445
446    /*
447     * See if the watchdog is enabled.  If it is, turn it off.
448     */
449
450    b = time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_BL);
451
452    if (b != (X1241REG_BL_WD1 | X1241REG_BL_WD0)) {
453
454	time_writertc(chan,
455		      X1241_CCR_ADDRESS,
456		      X1241REG_SR,
457		      X1241REG_SR_WEL);
458
459	time_writertc(chan,
460		      X1241_CCR_ADDRESS,
461		      X1241REG_SR,
462		      X1241REG_SR_WEL | X1241REG_SR_RWEL);
463
464	time_writertc(chan,
465		      X1241_CCR_ADDRESS,
466		      X1241REG_BL,
467		      (X1241REG_BL_WD1 | X1241REG_BL_WD0));
468
469	time_writertc(chan,
470		      X1241_CCR_ADDRESS,
471		      X1241REG_SR,
472		      0);
473	}
474
475    return (b < 0) ? -1 : 0;
476}
477
478/*  *********************************************************************
479    *  x1241_clock_read(ctx,buffer)
480    *
481    *  Read time/date from the RTC. Read a total of 8 bytes in this format:
482    *  hour-minute-second-month-day-year1-year2
483    *
484    *  Input parameters:
485    *  	   ctx - device context (can obtain our softc here)
486    *  	   buffer - buffer descriptor (target buffer, length, offset)
487    *
488    *  Return value:
489    *  	   number of bytes read
490    *  	   -1 if an error occured
491    ********************************************************************* */
492
493static int x1241_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
494{
495
496    x1241_clock_t *softc = ctx->dev_softc;
497    uint8_t byte;
498    unsigned char *bptr;
499    int chan = softc->smbus_channel;
500
501    bptr = buffer->buf_ptr;
502
503    byte = (uint8_t)  time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_HR);
504    byte &= ~X1241REG_HR_MIL;
505    *bptr++ = (unsigned char) byte;
506
507    byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_MN);
508    *bptr++ = (unsigned char) byte;
509
510    byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_SC);
511    *bptr++ = (unsigned char) byte;
512
513    byte =  (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_MO);
514    *bptr++ = (unsigned char) byte;
515
516    byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_DT);
517    *bptr++ = (unsigned char) byte;
518
519    byte =  (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_YR);
520    *bptr++ = (unsigned char) byte;
521
522    byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_Y2K);
523    *bptr = (unsigned char) byte;
524
525    byte = (uint8_t) time_readrtc(chan,X1241_CCR_ADDRESS,X1241REG_SR);
526
527    /*Last byte is status of battery*/
528    if (byte & X1241REG_SR_RTCF)
529    {
530      printf("Warning: Battery has failed.  Clock setting is not accurate.\n");
531    }
532
533    buffer->buf_retlen = 8;
534    return 0;
535}
536
537/*  *********************************************************************
538    *  x1241_clock_write(ctx,buffer)
539    *
540    *  Write time/date to the RTC. Write in this format:
541    *  hour-minute-second-month-day-year1-year2-(time/date flag)
542    *
543    *  Input parameters:
544    *  	   ctx - device context (can obtain our softc here)
545    *  	   buffer - buffer descriptor (target buffer, length, offset)
546    *
547    *  Return value:
548    *  	   number of bytes written
549    *  	   -1 if an error occured
550    ********************************************************************* */
551
552static int x1241_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
553{
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;
560
561    bptr = buffer->buf_ptr;
562    timeDateFlag = *(bptr + 7);
563
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);
568
569    /* write time or date */
570    if(timeDateFlag == SET_TIME) {
571
572	hr = (uint8_t) *bptr;
573	time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_HR, BCD(hr) | X1241REG_HR_MIL);
574
575	min = (uint8_t) *(bptr+1);
576	time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_MN, BCD(min) );
577
578	sec = (uint8_t) *(bptr+2);
579	time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_SC, BCD(sec) );
580
581	buffer->buf_retlen = 3;
582	}
583    else if(timeDateFlag == SET_DATE) {
584
585	mo = (uint8_t) *(bptr+3);
586	time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_MO, BCD(mo) );
587
588	day = (uint8_t) *(bptr+4);
589	time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_DT, BCD(day) );
590
591	yr = (uint8_t) *(bptr+5);
592	time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_YR, BCD(yr) );
593
594	y2k = (uint8_t) *(bptr+6);
595	time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_Y2K, BCD(y2k) );
596
597	buffer->buf_retlen = 4;
598	}
599    else {
600	return -1;
601	}
602
603    /* lock writes again */
604    time_writertc(chan,X1241_CCR_ADDRESS,X1241REG_SR,0);
605
606    return 0;
607}
608
609/*  *********************************************************************
610    *  x1241_clock_inpstat(ctx,inpstat)
611    *
612    *  Test input (read) status for the device
613    *
614    *  Input parameters:
615    *  	   ctx - device context (can obtain our softc here)
616    *  	   inpstat - input status descriptor to receive value
617    *
618    *  Return value:
619    *  	   0 if ok
620    *  	   -1 if an error occured
621    ********************************************************************* */
622
623static int x1241_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
624{
625    inpstat->inp_status = 1;
626
627    return 0;
628}
629
630/*  *********************************************************************
631    *  x1241_clock_ioctl(ctx,buffer)
632    *
633    *  Perform miscellaneous I/O control operations on the device.
634    *
635    *  Input parameters:
636    *  	   ctx - device context (can obtain our softc here)
637    *  	   buffer - buffer descriptor (target buffer, length, offset)
638    *
639    *  Return value:
640    *  	   number of bytes read
641    *  	   -1 if an error occured
642    ********************************************************************* */
643
644static int x1241_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
645{
646  return 0;
647}
648
649/*  *********************************************************************
650    *  x1241_clock_close(ctx,buffer)
651    *
652    *  Close the device.
653    *
654    *  Input parameters:
655    *  	   ctx - device context (can obtain our softc here)
656    *
657    *  Return value:
658    *  	   0 if ok
659    *  	   -1 if an error occured
660    ********************************************************************* */
661
662static int x1241_clock_close(cfe_devctx_t *ctx)
663{
664    return 0;
665}
666
667
668
669
670
671
672
673
674