summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/dev/dev_ds17887clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/dev/dev_ds17887clock.c')
-rw-r--r--cfe/cfe/dev/dev_ds17887clock.c422
1 files changed, 422 insertions, 0 deletions
diff --git a/cfe/cfe/dev/dev_ds17887clock.c b/cfe/cfe/dev/dev_ds17887clock.c
new file mode 100644
index 0000000..2ee82a3
--- /dev/null
+++ b/cfe/cfe/dev/dev_ds17887clock.c
@@ -0,0 +1,422 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * DS17887-3 RTC driver File: dev_sb1250_ds17887clock.c
+ *
+ * This module contains a CFE driver for a DS17887-3 generic bus
+ * real-time-clock.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+#include "lib_types.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_ioctl.h"
+
+#include "lib_physio.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+/*
+ * Register bits
+ */
+
+#define DS17887REGA_UIP 0x80 /* Update-in-progress */
+#define DS17887REGA_DV2 0x40 /* Countdown chain */
+#define DS17887REGA_DV1 0x20 /* Oscillator enable */
+#define DS17887REGA_DV0 0x10 /* Bank Select */
+#define DS17887REGA_RS3 0x08 /* Rate-selection bits */
+#define DS17887REGA_RS2 0x04
+#define DS17887REGA_RS1 0x02
+#define DS17887REGA_RS0 0x01
+
+#define DS17887REGB_SET 0x80 /* Set bit */
+#define DS17887REGB_PIE 0x40 /* Periodic Interrupt Enable */
+#define DS17887REGB_AIE 0x20 /* Alarm Interrupt Enable */
+#define DS17887REGB_UIE 0x10 /* Update-ended Interrupt Enable */
+#define DS17887REGB_SQWE 0x08 /* Square-wave Enable */
+#define DS17887REGB_DM 0x04 /* Data Mode (binary) */
+#define DS17887REGB_24 0x02 /* 24-hour mode control bit */
+#define DS17887REGB_DSE 0x01 /* Daylight Savings Enable */
+
+#define DS17887REGC_IRQF 0x80 /* Interrupt request flag */
+#define DS17887REGC_PF 0x40 /* Periodic interrupt flag */
+#define DS17887REGC_AF 0x20 /* Alarm interrupt flag */
+#define DS17887REGC_UF 0x10 /* Update ended interrupt flag */
+
+#define DS17887REGD_VRT 0x80 /* Valid RAM and time */
+
+/*
+ * Register numbers
+ */
+
+#define DS17887REG_SC 0x00 /* seconds */
+#define DS17887REG_SCA 0x01 /* seconds alarm */
+#define DS17887REG_MN 0x02 /* minutes */
+#define DS17887REG_MNA 0x03 /* minutes alarm */
+#define DS17887REG_HR 0x04 /* hours */
+#define DS17887REG_HRA 0x05 /* hours alarm */
+#define DS17887REG_DW 0x06 /* day of week */
+#define DS17887REG_DM 0x07 /* day of month */
+#define DS17887REG_MO 0x08 /* month */
+#define DS17887REG_YR 0x09 /* year */
+#define DS17887REG_A 0x0A /* register A */
+#define DS17887REG_B 0x0B /* register B */
+#define DS17887REG_C 0x0C /* register C */
+#define DS17887REG_D 0x0D /* register D */
+
+#define DS17887REG_CE 0x48 /* century (bank 1 only) */
+
+#define BCD(x) (((x) % 10) + (((x) / 10) << 4))
+#define SET_TIME 0x00
+#define SET_DATE 0x01
+
+#define WRITECSR(p,v) phys_write8((p),(v))
+#define READCSR(p) phys_read8((p))
+
+/* *********************************************************************
+ * Forward declarations
+ ********************************************************************* */
+
+static void ds17887_clock_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr);
+
+static int ds17887_clock_open(cfe_devctx_t *ctx);
+static int ds17887_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ds17887_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
+static int ds17887_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ds17887_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
+static int ds17887_clock_close(cfe_devctx_t *ctx);
+
+
+/* *********************************************************************
+ * Device dispatch
+ ********************************************************************* */
+
+const static cfe_devdisp_t ds17887_clock_dispatch = {
+ ds17887_clock_open,
+ ds17887_clock_read,
+ ds17887_clock_inpstat,
+ ds17887_clock_write,
+ ds17887_clock_ioctl,
+ ds17887_clock_close,
+ NULL,
+ NULL
+};
+
+const cfe_driver_t ds17887_clock = {
+ "DS17887 RTC",
+ "clock",
+ CFE_DEV_CLOCK,
+ &ds17887_clock_dispatch,
+ ds17887_clock_probe
+};
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+typedef struct ds17887_clock_s {
+ physaddr_t clock_base;
+} ds17887_clock_t;
+
+/* *********************************************************************
+ * ds17887_clock_probe(drv,a,b,ptr)
+ *
+ * Probe routine for this driver. This routine creates the
+ * local device context and attaches it to the driver list
+ * within CFE.
+ *
+ * Input parameters:
+ * drv - driver handle
+ * a,b - probe hints (longs)
+ * ptr - probe hint (pointer)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void ds17887_clock_probe(cfe_driver_t *drv,
+ unsigned long probe_a, unsigned long probe_b,
+ void *probe_ptr)
+{
+ ds17887_clock_t *softc;
+ char descr[80];
+
+ softc = (ds17887_clock_t *) KMALLOC(sizeof(ds17887_clock_t),0);
+
+ /*
+ * Probe_a is the clock base address
+ * Probe_b is unused.
+ * Probe_ptr is unused.
+ */
+
+ softc->clock_base = probe_a;
+
+ xsprintf(descr,"%s at 0x%X",
+ drv->drv_description,(uint32_t)probe_a);
+ cfe_attach(drv,softc,NULL,descr);
+
+}
+
+/* *********************************************************************
+ * ds17887_clock_open(ctx)
+ *
+ * Open this device. For the DS17887, we do a quick test
+ * read to be sure the device is out there.
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int ds17887_clock_open(cfe_devctx_t *ctx)
+{
+ ds17887_clock_t *softc = ctx->dev_softc;
+ uint8_t byte;
+ physaddr_t clockbase;
+
+ clockbase = softc->clock_base;
+
+ /* Make sure battery is still good and RTC valid */
+ if ( !(READCSR(clockbase+DS17887REG_D) & DS17887REGD_VRT) ) {
+ printf("Warning: Battery has failed. Clock setting is not accurate.\n");
+ }
+
+ /* Switch to bank 1. Mainly for century byte */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_A) & 0xFF);
+ WRITECSR(clockbase+DS17887REG_A,DS17887REGA_DV0 | DS17887REGA_DV1 | byte);
+
+ /* Set data mode to BCD, 24-hour mode, and enable daylight savings */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_B) & 0xFF);
+ byte &= (~DS17887REGB_DM & ~DS17887REGB_AIE);
+ WRITECSR(clockbase+DS17887REG_B, DS17887REGB_24 | DS17887REGB_DSE | byte );
+
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_read(ctx,buffer)
+ *
+ * Read time/date from the RTC. Read a total of 8 bytes in this format:
+ * hour-minute-second-month-day-year1-year2
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * buffer - buffer descriptor (target buffer, length, offset)
+ *
+ * Return value:
+ * number of bytes read
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+
+ ds17887_clock_t *softc = ctx->dev_softc;
+ unsigned char *bptr;
+ physaddr_t clockbase;
+
+ clockbase = softc->clock_base;
+
+ bptr = buffer->buf_ptr;
+
+ *bptr++ = READCSR(clockbase+DS17887REG_HR);
+ *bptr++ = READCSR(clockbase+DS17887REG_MN);
+ *bptr++ = READCSR(clockbase+DS17887REG_SC);
+ *bptr++ = READCSR(clockbase+DS17887REG_MO);
+ *bptr++ = READCSR(clockbase+DS17887REG_DM);
+ *bptr++ = READCSR(clockbase+DS17887REG_YR);
+ *bptr++ = READCSR(clockbase+DS17887REG_CE);
+
+ buffer->buf_retlen = 8;
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_write(ctx,buffer)
+ *
+ * Write time/date to the RTC. Write in this format:
+ * hour-minute-second-month-day-year1-year2-(time/date flag)
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * buffer - buffer descriptor (target buffer, length, offset)
+ *
+ * Return value:
+ * number of bytes written
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ ds17887_clock_t *softc = ctx->dev_softc;
+ uint8_t byte;
+ unsigned char *bptr;
+ uint8_t hr,min,sec;
+ uint8_t mo,day,yr,y2k;
+ uint8_t timeDateFlag;
+ physaddr_t clockbase;
+
+ clockbase = softc->clock_base;
+
+ bptr = buffer->buf_ptr;
+
+ /* Set SET bit */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_B) & 0xFF);
+ WRITECSR(clockbase+DS17887REG_B,DS17887REGB_SET | byte);
+
+ timeDateFlag = *(bptr + 7);
+
+ /* write time or date */
+ if(timeDateFlag == SET_TIME) {
+
+ hr = (uint8_t) *bptr;
+ WRITECSR(clockbase+DS17887REG_HR,BCD(hr));
+
+ min = (uint8_t) *(bptr+1);
+ WRITECSR(clockbase+DS17887REG_MN,BCD(min));
+
+ sec = (uint8_t) *(bptr+2);
+ WRITECSR(clockbase+DS17887REG_SC,BCD(sec));
+
+ buffer->buf_retlen = 3;
+ }
+ else if(timeDateFlag == SET_DATE) {
+
+ mo = (uint8_t) *(bptr+3);
+ WRITECSR(clockbase+DS17887REG_MO,BCD(mo));
+
+ day = (uint8_t) *(bptr+4);
+ WRITECSR(clockbase+DS17887REG_DM,BCD(day));
+
+ yr = (uint8_t) *(bptr+5);
+ WRITECSR(clockbase+DS17887REG_YR,BCD(yr));
+
+ y2k = (uint8_t) *(bptr+6);
+ WRITECSR(clockbase+DS17887REG_CE,y2k);
+
+ buffer->buf_retlen = 4;
+ }
+ else {
+ return -1;
+ }
+
+ /* clear SET bit */
+ byte = (uint8_t) (READCSR(clockbase+DS17887REG_B) & 0xFF);
+ WRITECSR(clockbase+DS17887REG_B,~DS17887REGB_SET & byte);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_inpstat(ctx,inpstat)
+ *
+ * Test input (read) status for the device
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * inpstat - input status descriptor to receive value
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
+{
+ inpstat->inp_status = 1;
+
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_ioctl(ctx,buffer)
+ *
+ * Perform miscellaneous I/O control operations on the device.
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ * buffer - buffer descriptor (target buffer, length, offset)
+ *
+ * Return value:
+ * number of bytes read
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
+{
+ return 0;
+}
+
+/* *********************************************************************
+ * ds17887_clock_close(ctx,buffer)
+ *
+ * Close the device.
+ *
+ * Input parameters:
+ * ctx - device context (can obtain our softc here)
+ *
+ * Return value:
+ * 0 if ok
+ * -1 if an error occured
+ ********************************************************************* */
+
+static int ds17887_clock_close(cfe_devctx_t *ctx)
+{
+ return 0;
+}
+
+
+
+
+
+
+
+