patch-2.1.80 linux/arch/arm/kernel/iic.c
Next file: linux/arch/arm/kernel/init_task.c
Previous file: linux/arch/arm/kernel/head-armv.S
Back to the patch index
Back to the overall index
- Lines: 161
- Date:
Tue Jan 20 16:39:41 1998
- Orig file:
v2.1.79/linux/arch/arm/kernel/iic.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/iic.c linux/arch/arm/kernel/iic.c
@@ -0,0 +1,160 @@
+/*
+ * linux/arch/arm/kernel/iic.c
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ *
+ * IIC is used to get the current time from the CMOS rtc.
+ */
+
+#include <asm/system.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+/*
+ * if delay loop has been calibrated then us that,
+ * else use IOC timer 1.
+ */
+static void iic_delay (void)
+{
+ extern unsigned long loops_per_sec;
+ if (loops_per_sec != (1 << 12)) {
+ udelay(10);
+ return;
+ } else {
+ unsigned long flags;
+ save_flags_cli(flags);
+
+ outb(254, IOC_T1LTCHL);
+ outb(255, IOC_T1LTCHH);
+ outb(0, IOC_T1GO);
+ outb(1<<6, IOC_IRQCLRA); /* clear T1 irq */
+ outb(4, IOC_T1LTCHL);
+ outb(0, IOC_T1LTCHH);
+ outb(0, IOC_T1GO);
+ while ((inb(IOC_IRQSTATA) & (1<<6)) == 0);
+ restore_flags(flags);
+ }
+}
+
+static inline void iic_start (void)
+{
+ unsigned char out;
+
+ out = inb(IOC_CONTROL) | 0xc2;
+
+ outb(out, IOC_CONTROL);
+ iic_delay();
+
+ outb(out ^ 1, IOC_CONTROL);
+ iic_delay();
+}
+
+static inline void iic_stop (void)
+{
+ unsigned char out;
+
+ out = inb(IOC_CONTROL) | 0xc3;
+
+ iic_delay();
+ outb(out ^ 1, IOC_CONTROL);
+
+ iic_delay();
+ outb(out, IOC_CONTROL);
+}
+
+static int iic_sendbyte (unsigned char b)
+{
+ unsigned char out, in;
+ int i;
+
+ out = (inb(IOC_CONTROL) & 0xfc) | 0xc0;
+
+ outb(out, IOC_CONTROL);
+ for (i = 7; i >= 0; i--) {
+ unsigned char c;
+ c = out | ((b & (1 << i)) ? 1 : 0);
+
+ outb(c, IOC_CONTROL);
+ iic_delay();
+
+ outb(c | 2, IOC_CONTROL);
+ iic_delay();
+
+ outb(c, IOC_CONTROL);
+ }
+ outb(out | 1, IOC_CONTROL);
+ iic_delay();
+
+ outb(out | 3, IOC_CONTROL);
+ iic_delay();
+
+ in = inb(IOC_CONTROL) & 1;
+
+ outb(out | 1, IOC_CONTROL);
+ iic_delay();
+
+ outb(out, IOC_CONTROL);
+ iic_delay();
+
+ if(in) {
+ printk("No acknowledge from RTC\n");
+ return 1;
+ } else
+ return 0;
+}
+
+static unsigned char iic_recvbyte (void)
+{
+ unsigned char out, in;
+ int i;
+
+ out = (inb(IOC_CONTROL) & 0xfc) | 0xc0;
+
+ outb(out, IOC_CONTROL);
+ in = 0;
+ for (i = 7; i >= 0; i--) {
+ outb(out | 1, IOC_CONTROL);
+ iic_delay();
+ outb(out | 3, IOC_CONTROL);
+ iic_delay();
+ in = (in << 1) | (inb(IOC_CONTROL) & 1);
+ outb(out | 1, IOC_CONTROL);
+ iic_delay();
+ }
+ outb(out, IOC_CONTROL);
+ iic_delay();
+ outb(out | 2, IOC_CONTROL);
+ iic_delay();
+
+ return in;
+}
+
+void iic_control (unsigned char addr, unsigned char loc, unsigned char *buf, int len)
+{
+ iic_start();
+
+ if (iic_sendbyte(addr & 0xfe))
+ goto error;
+
+ if (iic_sendbyte(loc))
+ goto error;
+
+ if (addr & 1) {
+ int i;
+
+ for (i = 0; i < len; i++)
+ if (iic_sendbyte (buf[i]))
+ break;
+ } else {
+ int i;
+
+ iic_stop();
+ iic_start();
+ iic_sendbyte(addr|1);
+ for (i = 0; i < len; i++)
+ buf[i] = iic_recvbyte ();
+ }
+error:
+ iic_stop();
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov